home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / msc / mscknl.txt < prev    next >
Encoding:
Text File  |  2013-11-08  |  3.0 MB  |  87,182 lines

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1.  Microsoft `C' Professional Development Environment
  2.  =============================================================================
  3.  
  4.  
  5.  1. C_FILE_INFO in Environment of Child Process
  6.  
  7.  Product Version(s): 3.00 4.00 5.00
  8.  Operating System:   MS-DOS
  9.  Flags: ENDUSER | TAR55563
  10.  Last Modified: 25-AUG-1989    ArticleIdent: Q11867
  11.  
  12.  When you shell from a C program (spawn a process), the environment
  13.  will appear to become corrupted with a ;C_FILE_INFO (or _C_FILE_INFO)
  14.  string. (Version 5.10 uses an underscore rather than a semicolon.)
  15.  
  16.  When a process is spawned, the C run time passes information about
  17.  open files to the child by inserting the identifier ";C_FILE_INFO" (or
  18.  "_C_FILE_INFO" -- no quotation marks in either case), followed by up
  19.  to 20 bytes, into the environment. During start-up, the C run time
  20.  reads the identifier, uses the information passed, and removes it from
  21.  the environment.
  22.  
  23.  System() is implemented by spawning COMMAND.COM, and since COMMAND.COM
  24.  is not a C program, ";C_FILE_INFO" (or "_C_FILE_INFO") gets left in
  25.  the environment.
  26.  
  27.  This behavior is harmless. The leading ";" (or "_") prevents any
  28.  collision with user-entered environment variables.
  29.  
  30.  
  31.  2. matherr and Trapping Floating-Point Errors
  32.  
  33.  Product Version(s): 4.00 5.00 5.10
  34.  Operating System:   MS-DOS
  35.  Flags: ENDUSER |
  36.  Last Modified: 15-JAN-1990    ArticleIdent: Q22317
  37.  
  38.  Question:
  39.  
  40.  matherr is not trapping my floating point errors. Could you give me
  41.  some advice on what I could be doing wrong?
  42.  
  43.  Response:
  44.  
  45.  matherr (Page 274 in the "Microsoft C Run-Time Library Reference"
  46.  manual) does not trap in-line floating-point errors. matherr only
  47.  traps floating-point errors generated by functions in our math
  48.  libraries. For example, the following program returns control to our
  49.  matherr routine, not yours:
  50.  
  51.     #include <math.h>
  52.  
  53.     matherr(x)
  54.     struct exception *x;
  55.     {
  56.     x->retval=2;
  57.     return(1);
  58.     }
  59.  
  60.     main()
  61.     {
  62.     double f;
  63.     f=2.0;
  64.     while (1)
  65.     f*=f;
  66.     }
  67.  
  68.  To trap in-line floating-point errors such as the one above, we
  69.  recommend that you use signal with SIGFPE (see the run-time reference
  70.  manual).
  71.  
  72.  
  73.  3. C 5.10 Prototypes Differ Between \INCLUDE and \INCLUDE\MT
  74.  
  75.  Product Version(s): 5.10
  76.  Operating System:   OS/2
  77.  Flags: ENDUSER |
  78.  Last Modified:  1-FEB-1991    ArticleIdent: Q58069
  79.  
  80.  Multithreaded programs are linked with LLIBCMT.LIB and include header
  81.  files from the \INCLUDE\MT directory. If you link with LLIBCMT, but
  82.  include header files from the \INCLUDE directory, you may get the
  83.  linker message "L2029, unresolved external" on one or more of the C
  84.  run-time routines. You can resolve the problem by including the
  85.  multithreaded header files.
  86.  
  87.  The linker must resolve external references based on the names written
  88.  to the object file. The explicit format of these names is directly
  89.  affected by the prototypes you use in your program, and when you
  90.  include the header files, you are specifying function prototypes. The
  91.  prototypes for some functions are different between the single and
  92.  multithreaded header files. For example, atof() is defined in the
  93.     double _CDECL atof(const char *);
  94.  
  95.  and in \INCLUDE\MT\STDLIB.H as follows:
  96.  
  97.     double far pascal atof(const char far *);
  98.  
  99.  The keyword _CDECL means to use C language conventions (that is,
  100.  preserve case and prepend a leading underscore). The keyword pascal
  101.  means to use Pascal language conventions (that is, promote to
  102.  uppercase and do not add a leading underscore). When the linker is
  103.  looking for _atof, it does not consider ATOF a match.
  104.  
  105.  You can find complete compile and link instructions for multithreaded
  106.  programming in MTDYNA.DOC, which is on the C version 5.10 disks.
  107.  
  108.  
  109.  4. _remappalette(8,_GRAY) Does Not Work Correctly
  110.  
  111.  Product Version(s): 5.10   | 5.10
  112.  Operating System:   MS-DOS | OS/2
  113.  Flags: ENDUSER | bug
  114.  Last Modified: 12-OCT-1988    ArticleIdent: Q34623
  115.  
  116.  _remappalette(pixel,color) maps the number "pixel" to the value
  117.  "color" and is suppose to return the previous color value. However,
  118.  when this function is invoked as _remappalette(8,_GRAY), the value
  119.  associated with _WHITE is returned.
  120.  
  121.  Microsoft is researching this problem and will post new information as
  122.  it becomes available.
  123.  
  124.  To demonstrate this problem, do the following:
  125.  
  126.  1. cl the following source-code chunklet with /Od /Zi
  127.     switches.
  128.  
  129.  2. Go into CodeView.
  130.  
  131.  3. Set N16 to look at the value err returned by _remappalette() in hex,
  132.     then compare the value with values for the colors in graph.h. You
  133.     may want to make a hardcopy of these values prior to cving. The
  134.     correct value is returned on the zeroth pass, but then erroneous
  135.     values are returned. This has been raided.
  136.  
  137.  4. Use cv /S, where the S is for switching screen modes.
  138.  
  139.  The following sample code demonstrates the problem:
  140.  
  141.           #include <stdio.h>
  142.           #include <graph,h>
  143.           main()
  144.           {
  145.              int i;
  146.              long err;
  147.              _setvideomode(_HRES16COLOR);
  148.              for (i=0;i<16;i++)
  149.              {
  150.                err=_remappalette(8,_GRAY);
  151.                printf("%x\n",err);
  152.              }
  153.              _setvideomode(_DEFAULTMODE);
  154.           }
  155.  
  156.  
  157.  5. Warning C4040: near/far/huge Ignored
  158.  
  159.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  160.  Operating System:   MS-DOS              | OS/2
  161.  Flags: ENDUSER |
  162.  Last Modified: 26-SEP-1988    ArticleIdent: Q23978
  163.  
  164.  Question:
  165.  
  166.  I am trying to declare some far data in small model, but I keep
  167.  getting "Warning 40: near/far/huge ignored" with C Version 4.00, or
  168.  the same warning with the number C4040 using C Versions 5.x. Does this
  169.  mean I cannot declare far data in the small model?
  170.  
  171.  Response:
  172.  
  173.  The far data can be declared in the small-memory model. This warning
  174.  means that the far descriptor is improper and/or unnecessary in the
  175.  context in which it is being used. Far or huge arrays should be
  176.  defined outside of functions, or with the static storage class if
  177.  defined within functions.
  178.  
  179.  It also may mean you are trying to make the type of pointer definition
  180.  "char * far pvar;" within the body of a function. This definition
  181.  attempts to define a pointer to data (either near or far, depending on
  182.  the memory model) and place it in a far data segment outside the
  183.  default data segment. This process only will work properly if it is a
  184.  global definition, or if it is defined as static within the body of
  185.  the function.
  186.  
  187.  Please note the difference between the above definition and defining a
  188.  pointer to far data, which is "char far *pvar;". The latter definition
  189.  declares a pointer that can point to data outside the default data
  190.  segment, but the pointer itself is within the default data segment.
  191.  This declaration is quite acceptable within the body of a function.
  192.  
  193.  
  194.  6. Initial Memory Allocation of C Programs
  195.  
  196.  Product Version(s): 4.00 5.00 5.10
  197.  Operating System:   MS-DOS
  198.  Flags: ENDUSER | DGROUP 64K
  199.  Last Modified: 15-JAN-1990    ArticleIdent: Q23905
  200.  
  201.  Question:
  202.  
  203.  I want to make a program "terminate and stay resident." It is a very
  204.  short program with only 4K of data and about 2K of code. However, when
  205.  I execute the program to make it resident and do a CHKDSK, it seems to
  206.  occupy about 70K. Why does it take up so much space?
  207.  
  208.  Response:
  209.  
  210.  The linker normally allocates all of memory to a program. You can use
  211.  the /CP switch to adjust the allocation down. If you specify an amount
  212.  less than the minimum allocation, the maximum allocation will default
  213.  to that minimum, so link with /CP:1.
  214.  
  215.  You can also use the /max <MinimumAllocationInHexParagraphs> option of
  216.  the EXEMOD.EXE utility to adjust the maximum allocation of a program.
  217.  
  218.  Microsoft C was not designed for writing memory resident software.
  219.  Although it is possible, you also may need to make modifications to
  220.  the start-up code. Be cautious about what functions you use and what
  221.  DOS functions are called.
  222.  
  223.  
  224.  7. Changing STDIN Translation Mode from Text to Binary
  225.  
  226.  Product Version(s): 5.10   | 5.10
  227.  Operating System:   MS-DOS | OS/2
  228.  Flags: ENDUSER | s_quickc s_quickasm
  229.  Last Modified:  7-MAR-1990    ArticleIdent: Q58427
  230.  
  231.  Question:
  232.  
  233.  Why is it that when I enter a ^Z (CTRL+Z) for a string input in
  234.  response to gets() or scanf(), the next line does not prompt me for an
  235.  input?
  236.  
  237.  Response:
  238.  
  239.  Since STDIN is a predefined file pointer opened in text mode, and a ^Z
  240.  character is an end-of-file marker in DOS, the ^Z character
  241.  automatically closes the file pointer. The gets() or scanf() functions
  242.  do not stop to accept input from STDIN following the previous input
  243.  containing a ^Z character.
  244.  
  245.  To work around this problem, change the translation mode of STDIN from
  246.  text mode to binary mode. Since the ^Z character is not translated as
  247.  an end-of-file character in binary mode, the gets() from the following
  248.  example only accepts input following a ^Z from STDIN after the
  249.  translation.
  250.  
  251.  To change STDIN from text mode to binary mode, use the setmode()
  252.  run-time function to change the translation mode. The following code
  253.  demonstrates this behavior, and includes the setmode() function to
  254.  show how to change STDIN from text mode to binary mode. Remove the
  255.  comment delimiters to observe the difference in the program's behavior
  256.  after adding the setmode() function.
  257.  
  258.  Code Example
  259.  ------------
  260.  
  261.  #include <stdio.h>
  262.  #include <string.h>
  263.  #include <fcntl.h>
  264.  
  265.  void main (void)
  266.  {
  267.     char str1[20];
  268.  
  269.  /* if( setmode ( fileno ( stdin ), O_BINARY ) == -1 )
  270.            perror ( "Cannot set stdin to binary mode" );
  271.     else
  272.            printf ( "stdin mode successfully set to binary\n" );
  273.  */
  274.     do {
  275.            printf ( "Enter a string : " );
  276.            gets ( str1 );
  277.     } while ( strcmp( str1,"n" ) );
  278.  
  279.  }
  280.  
  281.  Compile the above code and run the program. If you enter a string
  282.  and then press the ENTER key, the program will loop and prompt for
  283.  another string. However, if at the prompt you enter a ^Z or a string
  284.  followed by a ^Z, the program will loop indefinitely. It does not pause
  285.  at the gets() statement and wait for your input.
  286.  
  287.  Now, uncomment the if-else clause. Recompile the program and run it.
  288.  Input that includes a ^Z character is now accepted without infinite
  289.  looping.
  290.  
  291.  
  292.  8. Evaluation Order of Expression and Function Args Undefined
  293.  
  294.  Product Version(s): 5.10
  295.  Operating System:   MS-DOS  | OS/2
  296.  Flags: ENDUSER | S_QUICKC S_QUICKASM
  297.  Last Modified: 30-NOV-1989    ArticleIdent: Q50694
  298.  
  299.  Side effect operators (++, --, =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=,
  300.  and >>=) may cause unexpected results if they are used on the same
  301.  variable or memory location more than once in the same expression. The
  302.  order in which side effects occur within an expression is not
  303.  specified.
  304.  
  305.  Do NOT expect any specific order of evaluation to take place. The
  306.  discretion is left to the compiler on how it implements the evaluation
  307.  order. The evaluation order could be affected by machine architecture
  308.  and code optimization. Although such code may work sometimes, it is
  309.  not guaranteed to work, and is therefore unsafe.
  310.  
  311.  Note: Kernighan and Ritchie do an excellent job explaining the ANSI C
  312.  Standard for the evaluation order of expressions in Section 2.12 of
  313.  "The C Programming Language - 2nd Edition" by Kernighan and Ritchie.
  314.  
  315.  It is very easy to accidentally write nonportable code with the C
  316.  language. Below are some other common examples of statements that can
  317.  cause side effects during run time:
  318.  
  319.     printf("%d %d \n", ++n, power(2, n));   /* WRONG */
  320.  
  321.  The above statement can produce different results with different
  322.  compilers, depending on whether "n" is incremented before "power" is
  323.  called. The correct code would look like the following:
  324.  
  325.        n++;                                  /* CORRECT */
  326.        printf("%d %d \n", n, power(2, n));
  327.  
  328.  Another common pitfall is the following:
  329.  
  330.        a[i] = i++;     /* WRONG */
  331.  
  332.  The question is whether the subscript of "a" is the old value of "i"
  333.  or the new value. Again the correct code would be the following:
  334.  
  335.        a[i] = a[i+1];    /* CORRECT */
  336.        i++;
  337.  
  338.  Another example is as follows:
  339.  
  340.        int x[10], *p = x;
  341.  
  342.        *p++ = *p++ = 0;  /* WRONG */
  343.  
  344.  The compiler is allowed to "p" twice at the end after doing the two
  345.  assignments, if it so chooses. To ensure correct code generation, you
  346.  must code as follows:
  347.  
  348.        *p++ = 0;  *p++ = 0;   /* CORRECT */
  349.  
  350.  In general, any object may have its stored value modified at most once
  351.  in a single expression; in addition, the prior value shall be accessed
  352.  only to determine the value to be stored. Therefore,
  353.  
  354.        i = i + 1;    /* OK */
  355.  
  356.  is allowed because "i" is modified only once, and "i" is accessed only
  357.  to determine what to store in "i", but
  358.  
  359.        i = ++i + 1;  /* UNDEFINED */
  360.  
  361.  is undefined because "i" is modified more than once in the course of
  362.  the evaluation of the expression.
  363.  
  364.  Instead, the following pair of statements is correct:
  365.  
  366.        ++i;
  367.        i = i + 1;    /* OK */
  368.  
  369.  The statement
  370.  
  371.        a[i] = i++;  /* UNDEFINED */
  372.  
  373.  is undefined, because, although "i" is only modified once, it is
  374.  accessed both to determine the value to be stored in "i" by the ++
  375.  operator and as a subscript.
  376.  
  377.  
  378.  9. Memory Not Freed by DOS 2.x for exec or spawn with P_OVERLAY
  379.  
  380.  Product Version(s): 4.00 5.00 5.10
  381.  Operating System:   MS-DOS
  382.  Flags: ENDUSER | tar57672
  383.  Last Modified: 21-SEP-1988    ArticleIdent: Q24910
  384.  
  385.  Within DOS Versions 2.x only, recurrent use of an exec function or a
  386.  spawn function with P_OVERLAY eventually causes a return indicating
  387.  that there is no more available RAM memory.
  388.  
  389.  This is a DOS Versions 2.x problem, whose exact nature is unknown.
  390.  Microsoft has traced the problem to the point where DOS corrupted
  391.  memory, and memory is not being freed back to DOS Versions 2.x.
  392.  
  393.  If you encounter this problem, upgrade to DOS Versions 3.x, which
  394.  do not have this problem.
  395.  
  396.  It appears that only the exec() family (or spawn() with P_OVERLAY
  397.  specified) is affected by this DOS problem. The spawn() family (except
  398.  when P_OVERLAY is specified) seems to work correctly.
  399.  
  400.  
  401.  10. Variables in C 5.00/5.10 splitpath() Example Declared Wrong
  402.  
  403.  Product Version(s): 5.00 5.10
  404.  Operating System:   MS-DOS
  405.  Flags: ENDUSER | docerr
  406.  Last Modified: 11-FEB-1991    ArticleIdent: Q26589
  407.  
  408.  On page 560 of the "Microsoft C Optimizing Compiler: Run-Time Library
  409.  Reference" that shipped with C versions 5.00 and 5.10, the example for
  410.  the _splitpath() function declares its variables incorrectly. It
  411.  declares arrays of pointers, rather than arrays of characters, as
  412.  follows:
  413.  
  414.     char * drive [3];
  415.     char * dir [30];
  416.     char * fname [9];
  417.     char * ext [4];
  418.  
  419.  The correct declaration should be as follows:
  420.  
  421.     char drive [3];
  422.     char dir [30];
  423.     char fname [9];
  424.     char ext [4];
  425.  
  426.  Both declarations work correctly, but unpredictable results may occur
  427.  with the original form of the array declarations.
  428.  
  429.  
  430.  11. _amblksiz Not Declared
  431.  
  432.  Product Version(s): 4.00 5.00 5.10
  433.  Operating System:   MS-DOS
  434.  Flags: ENDUSER | docerr
  435.  Last Modified: 26-SEP-1988    ArticleIdent: Q26778
  436.  
  437.  Page 33 of the "Microsoft C Compiler Run-Time Library Reference
  438.  Manual" (Page 31 for Version 4.00) incorrectly states that _amblksiz
  439.  "is declared in the include file malloc.h". It is not there.
  440.  
  441.  You can use the variable in your program by declaring the variable as
  442.  follows:
  443.  
  444.  extern unsigned int _amblksiz;
  445.  
  446.  
  447.  12. _remapallpalette Example Causes C4049 Warning
  448.  
  449.  Product Version(s): 5.00 5.10
  450.  Operating System:   MS-DOS
  451.  Flags: ENDUSER | docerr
  452.  Last Modified: 26-SEP-1988    ArticleIdent: Q27803
  453.  
  454.  Problem:
  455.  
  456.  I get a warning C4049 when I run the example on Page 489 of the C
  457.  Versions 5.00 and 5.10 "Run-Time Library Reference," in the section on
  458.  _remapallpalette and _remappalette.
  459.  
  460.  Response:
  461.  
  462.  There is an error in the example program. The following line:
  463.  
  464.  _remapallpalette((char *)(&(colorsarray[0])));
  465.  
  466.  should read as follows to avoid the warning message:
  467.  
  468.  _remapallpalette((long far *)(&(colorsarray[0])));
  469.  
  470.  
  471.  13. The struct videoconfig Declaration
  472.  
  473.  Product Version(s): 5.00 5.10
  474.  Operating System:   MS-DOS
  475.  Flags: ENDUSER | docerr
  476.  Last Modified: 26-SEP-1988    ArticleIdent: Q27804
  477.  
  478.  Page 342 of the "Microsoft C Run-Time Library Reference" manual for
  479.  Version 5.00 has an omission. The struct videoconfig declaration
  480.  member list leaves out the following four lines: mode, adaptor,
  481.  monitor, and memory.
  482.  
  483.  The following is the structure as shown in the manual (incorrect):
  484.  
  485.  struct videoconfig {
  486.    short numxpixels;   /* number of pixels on X axis */
  487.    short numypixels;   /* number of pixels on Y axis */
  488.    short numtextcols;  /* number of text columns available */
  489.    short numtextrows;  /* number of text rows available */
  490.    short numcolors;    /* number of actual colors */
  491.    short bitsperpixel; /* number of bits per pixel */
  492.    short numvideopages;/* number of available video pages */
  493.  }
  494.  
  495.  The following is the structure as defined in GRAPH.H (correct):
  496.  
  497.  struct videoconfig {
  498.    short numxpixels;   /* number of pixels on X axis */
  499.    short numypixels;   /* number of pixels on Y axis */
  500.    short numtextcols;  /* number of text columns available */
  501.    short numtextrows;  /* number of text rows available */
  502.    short numcolors;    /* number of actual colors */
  503.    short bitsperpixel; /* number of bits per pixel */
  504.    short numvideopages;/* number of available video pages */
  505.    short mode;         /* current video mode */
  506.    short adapter;      /* active display adapter */
  507.    short monitor;      /* active display monitor */
  508.    short memory;       /* adapter video memory in K bytes */
  509.  }
  510.  
  511.  
  512.  14. Beginner's Concerns for Writing Non-PM Graphic Applications
  513.  
  514.  Product Version(s): 5.10
  515.  Operating System:   OS/2
  516.  Flags: ENDUSER | TAR73919
  517.  Last Modified: 12-OCT-1988    ArticleIdent: Q28141
  518.  
  519.  Question:
  520.     I have an OS/2 application (an analog simulator with postprocessor)
  521.  that is ready to go, with the exception of the GRAPHICS output. I have
  522.  been having difficulties getting graphics to work under OS/2. Can you
  523.  give me any suggestions on how to use graphics?
  524.  
  525.  Response:
  526.     The first problem is to get "addressability" to the video RAM. This
  527.  is accomplished by using the VioGetPhysBuf API. For an EGA monitor the
  528.  calling sequence would be as follows:
  529.  
  530.  struct    PhysBufData physbuf;
  531.  char  far *base1, far *base2;
  532.  
  533.       physbuf.buf_start = 0xa0000;
  534.       physbuf.buf_length = 0x20000;
  535.       rcode = VIOGETPHYSBUF (&physbuf, 0);
  536.       FP_SEG (base1) = physbuf.selectors[0];
  537.       FP_OFF (base1) = 0;
  538.       FP_SEG (base2) = physbuf.selectors[1];
  539.       FP_OFF (base2) = 0;
  540.  
  541.  where base1 is the first 64K of memory on the EGA card, and base2
  542.  would be the next 64K of memory. If you wanted to access more than
  543.  128K you would have to increase the length and allocate space for more
  544.  physbuf.selectors. (Look up this API.)
  545.     Once you have valid pointers to the video memory, you still have
  546.  more limitations. You can (should) not use these pointers unless your
  547.  application is in the foreground. You must (should) inform the
  548.  operating system before using the pointers. You use the API VioScrLock
  549.  to lock your process into the foreground while you are writing to
  550.  video memory. Once you are done writing to the video memory you must
  551.  call VioScrUnLock, to re-enable screen switching. You should not keep
  552.  the screen locked on any more time then absolutely necessary. (See
  553.  this API for restrictions.) If your application attempts to write to
  554.  the video memory when it is not in the foreground, it will gp_fault.
  555.     Since your application is putting the monitor into graphics mode,
  556.  it is its responsibility to save and restore the monitor's contents
  557.  and mode. The application will have to use the API's VioSavRedrawWait
  558.  and VioModeWait. VioSavRedrawWait is for the notification of when you
  559.  should save or restore your screen image. VioModeWait is notified when
  560.  you should save and restore video modes.
  561.     Finally, if you plan to use I/O ports with your program you will
  562.  have to "flag" it as needing IOPL (input/output privilege level). You
  563.  do this by putting "CODE IOPL" in the program's definition file, and
  564.  in config.os2 "IOPL=YES".
  565.  
  566.  API's to review:
  567.       VioGetPhysBuf
  568.       VioScrLock
  569.       VioScrUnLock
  570.       VioModeWait
  571.       VioRedrawWait
  572.  
  573.  
  574.  15. Include Directories Not Searched as Expected
  575.  
  576.  Product Version(s): 5.10   | 5.10
  577.  Operating System:   MS-DOS | OS/2
  578.  Flags: ENDUSER |
  579.  Last Modified:  5-DEC-1988    ArticleIdent: Q38383
  580.  
  581.  Question:
  582.  
  583.  It appears that the C compiler searches the INCLUDE list in the wrong
  584.  order. Our INCLUDE=OS2\INC;\INC, but the compiler seemed to get an old
  585.  version of the .h file from \INC. Deleting the old versions from \INC
  586.  corrected the problem.
  587.  
  588.  Response:
  589.  
  590.  While the search order for a file enclosed in <>'s is simple, the
  591.  order for a file enclosed in ""'s is different and more complicated.
  592.  
  593.  You are probably using ""'s rather than <>'s around the filename, and
  594.  you've accidentally set up \INC as a "parent" or "grandparent"
  595.  directory. (See below for more information.) To correct the problem,
  596.  either use <>'s around the filename or reorganize your header files so
  597.  that the search order will find the right file.
  598.  
  599.  Note: if you use ""'s around a complete path specification, the
  600.  standard directories will NOT be searched.
  601.  
  602.  As documented on Page 202 in the "Microsoft C Language Reference" and
  603.  on Page 80 of the "Microsoft C Optimizing Compiler User's Guide," the
  604.  search order for #include <file.h> is as follows:
  605.  
  606.  1. Any directories specified using the /I switch on the cl command
  607.     line, from left to right
  608.  
  609.  2. Directories specified in the include environment variable, again
  610.     from left to right
  611.  
  612.  3. If the file is found in neither of these steps, the following
  613.     message is issued:
  614.  
  615.        fatal error C1015:  cannot open include file 'file.h'
  616.  
  617.  For the following example, only the "\path" directory on the current
  618.  default drive is searched:
  619.  
  620.     #include "\path\file.h"
  621.  
  622.  The standard directories will not be searched. However, the search
  623.  order for:
  624.  
  625.     #include "file.h"
  626.  
  627.  is similar to the search order for:
  628.  
  629.     #include <file.h>
  630.  
  631.  except that "parent directories" are searched before directories
  632.  specified by the /I switch and before directories specified in the
  633.  INCLUDE environment variable.
  634.  
  635.  The parent directory is the directory that contains the source
  636.  containing the #include directive. If #include files are nested, then
  637.  the parent directories are searched in reverse order of the nesting:
  638.  first parents, then grandparents, and so on.
  639.  
  640.  For example, if source file grandma.c contains:
  641.  
  642.     #include <parent.h>
  643.  
  644.  and parent.h contains:
  645.  
  646.     #include "child.h"
  647.  
  648.  the search for child.h would take place in the following order:
  649.  
  650.  1. The parent directory--in this case, the directory in which parent.h
  651.     was previously found.
  652.  
  653.  2. If child.h was not there, the directory that contains grandma.c
  654.     would be searched next.
  655.  
  656.  3. If child.h was still not found, the directories (if any) specified
  657.     in /I switches on the CL command line would be searched in
  658.     left-to-right order.
  659.  
  660.  4. If child.h was still not found, the directories (if any) specified
  661.     by the INCLUDE environment variable would be searched in
  662.     left-to-right order.
  663.  
  664.  5. If child.h was not found in any of these places, the compiler would
  665.     give the following message:
  666.  
  667.        fatal error C1015:  cannot open include file 'child.h'
  668.  
  669.  
  670.  16. Hexadecimal Unsigned Char Array Elements Missing "\"
  671.  
  672.  Product Version(s): 5.00 5.10
  673.  Operating System:   MS-DOS
  674.  Flags: ENDUSER | docerr
  675.  Last Modified: 12-OCT-1988    ArticleIdent: Q28349
  676.  
  677.  The sample programs on Pages 325 and 521 of the "Microsoft C 5.1
  678.  Optimizing Compiler Run-Time Library Reference" manual are incorrect.
  679.  For the _getfillmask and _setfillmask examples, the unsigned char
  680.  array element values should be shown with backslackes "\" preceding
  681.  the x's to indicate that they are hexadecimal values.
  682.  
  683.  
  684.  17. Reference Page 75 Example 9 Causes Error C2147
  685.  
  686.  Product Version(s): 5.00 5.10 | 5.10
  687.  Operating System:   MS-DOS    | OS/2
  688.  Flags: ENDUSER | docerr
  689.  Last Modified: 12-OCT-1988    ArticleIdent: Q28567
  690.  
  691.  Using example nine on Page 75 of the "Microsoft C 5.1 Optimizing
  692.  Compiler Language Reference" manual causes the compiler error
  693.  "C2147: array: unknown size" on the line "(int *) p++".
  694.  
  695.  The example is incorrect. Instead of using example nine, use one of
  696.  the two following examples:
  697.  
  698.  1. ((int*) p)++;
  699.  2. p = (void *) ((char *) p + sizeof(int));
  700.  
  701.  Note that the expression "((int *) p)++" is a non-standard extension
  702.  to the language, and the compiler will issue a warning.
  703.  
  704.  See Pages 99-100 of the user's guide for a discussion of enabling
  705.  and disabling language extensions with the /Ze and /Za switches.
  706.  There is an example at the bottom of Page 99, which is almost
  707.  identical.
  708.  
  709.  Example nine on Page 75 is as follows:
  710.  
  711.          int i;
  712.          void *p;
  713.  
  714.          p = &i;
  715.          (int *) p++;
  716.  
  717.  The expression "(int *) p++" generates the C2147 error because the
  718.  "++" operation is preformed before the "(int *)" cast. Thus, the
  719.  expression is trying to increment a pointer that points to a void.
  720.  Because void has no size, the compiler does not know how many bytes
  721.  "p" should be incremented by.
  722.  
  723.  By using the extra parentheses in the expression "((int *) p)++", you
  724.  are forcing the "(int *)" to convert "p" from a pointer-to-void to a
  725.  pointer-to-int, which can be incremented.
  726.  
  727.  The second workaround, "p = (void *) ((char *) p + sizeof(int))",
  728.  works correctly because you are telling the compiler how many bytes to
  729.  increment the pointer.
  730.  
  731.  The second workaround is standard ANSI C and should compile on any
  732.  standard ANSI C compiler.
  733.  
  734.  
  735.  
  736.  18. Example of TSR Program
  737.  
  738.  Product Version(s): 5.00 5.10
  739.  Operating System:   MS-DOS
  740.  Flags: ENDUSER | APPNOTE
  741.  Last Modified: 20-MAY-1988    ArticleIdent: Q28568
  742.  
  743.     The following article shows how to use Microsoft C to write a
  744.  terminate-and-stay-resident (TSR) program. The article also
  745.  illustrates the use of the following C run-time functions:
  746.  
  747.     _dos_setvect
  748.     _dos_getvect
  749.     _dos_keep
  750.     _chain_intr
  751.     spawnXXX
  752.  
  753.     The following example shows how to use Microsoft C to write a TSR
  754.  program:
  755.  
  756.  /**************************************************************/
  757.  /*                                                            */
  758.  /*                            DirZap.h                        */
  759.  /*                                                            */
  760.  /*       This header file defines global variables, macros,   */
  761.  /*       function pointers, and function prototypes           */
  762.  /*       necessary for the DirZap.c program.                  */
  763.  /*                                                            */
  764.  /**************************************************************/
  765.  
  766.  /* Global Variable For Macro SHIFTL(x, n)*/
  767.  long _ADDRESS;
  768.  
  769.  /* Macro Definitions */
  770.  #define INT5  0x5
  771.  #define INT21 0x21
  772.  #define SHIFTL(x, n) (_ADDRESS = 0L, _ADDRESS = (long) x, _ADDRESS << n)
  773.  #define HIBYTE(x) (((unsigned) (x) >> 8) & 0xff)
  774.  #define REGPAK unsigned es, unsigned ds, unsigned di, unsigned si,\
  775.                 unsigned bp, unsigned sp, unsigned bx, unsigned dx,\
  776.                 unsigned cx, unsigned ax, unsigned ip,unsigned  cs,\
  777.                 unsigned flags
  778.  
  779.  /* Function Pointers */
  780.  void (interrupt far *save_dir_adr)();
  781.     /* Saves address of the original interrupt service routine */
  782.  
  783.  void (interrupt far *set_dir_adr)();
  784.    /* This function pointer gets set to the address of the new
  785.     interrupt service routine 'set_dir' */
  786.  
  787.  void (interrupt far *reset_dir_adr)();
  788.     /* This function pointer gets set to the address of the new
  789.     interrupt service routine 'reset_dir' */
  790.  
  791.  /* Function Declarations */
  792.  void cdecl interrupt far set_dir(REGPAK);
  793.     /* This is the new service routine whichs zaps the directory
  794.     interrupt routines. */
  795.  
  796.  void interrupt far reset_dir(void);
  797.     /* This routine toggles between setting and disabling the
  798.     directory interrupt routines */
  799.  
  800.  unsigned _get_memsize(void);
  801.     /* This function gets the number of bytes to keep resident */
  802.  
  803.  short _set_shell(void);
  804.     /* Sets a DOS shell. */
  805.  
  806.  /**************************************************************/
  807.  /*                                                            */
  808.  /*                       DirZap.c                             */
  809.  /*                                                            */
  810.  /*        This is an illustration of a TSR program.           */
  811.  /*     It traps and zaps the directory interrupts for         */
  812.  /*     MkDir, RmDir, and ChDir. It also illustates how        */
  813.  /*     to set a DOS shell by executing a new version of       */
  814.  /*     COMMAND.COM.                                           */
  815.  /*                                                            */
  816.  /*     Copyright (c) Microsoft Corp 1988. All rights          */
  817.  /*     reserved.                                              */
  818.  /*                                                            */
  819.  /*        To run, do the following:                           */
  820.  /*                                                            */
  821.  /*        1. EXEPACK DirZap to save memory.                   */
  822.  /*        2. Type DirZap at DOS prompt. DirZap sets a         */
  823.  /*        DOS shell and is not yet active.                    */
  824.  /*        3. When "exit" is typed, DirZap is invoked.         */
  825.  /*                                                            */
  826.  /*        The PRINT SCREEN key now toggles                    */
  827.  /*        DirZap on and off, but no memory has been           */
  828.  /*        freed.                                              */
  829.  /*                                                            */
  830.  /**************************************************************/
  831.  /*                                                            */
  832.  /* NOTE:                                                      */
  833.  /*                                                            */
  834.  /* THIS PROGRAM, ITS USE, OPERATION, AND SUPPORT ARE PROVIDED */
  835.  /* "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR  */
  836.  /* IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED        */
  837.  /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
  838.  /* PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE */
  839.  /* OF THIS PROGRAM IS WITH THE USER. IN NO EVENT SHALL        */
  840.  /* MICROSOFT BE LIABLE FOR ANY DAMAGES INCLUDING, WITHOUT     */
  841.  /* LIMITATION, ANY LOST PROFITS, LOST SAVINGS OR OTHER        */
  842.  /* INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING FROM THE USE   */
  843.  /* OR INABILITY TO USE SUCH PROGRAM, EVEN IF MICROSOFT HAS    */
  844.  /* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES OR FOR ANY */
  845.  /* CLAIM BY ANY OTHER PARTY.                                  */
  846.  /*                                                            */
  847.  /**************************************************************/
  848.  #include <dos.h>
  849.  #include <stdio.h>
  850.  #include <stdlib.h>
  851.  #include <process.h>
  852.  #include <dirzap.h>
  853.  
  854.  extern unsigned _psp;
  855.     /* Pre-defined varible, _psp = segment address of PSP */
  856.  unsigned far *psp_pointer;
  857.     /* Used to retrieve the memsize to stay resident */
  858.  short hot_key=1;
  859.     /* Flag to toggle DirZap on and off once it is invoked */
  860.  
  861.  void main(void);
  862.  void main()
  863.  {
  864.     if (_set_shell())
  865.     {
  866.        /* Set trap for directory interrupts */
  867.        save_dir_adr = _dos_getvect(INT21);
  868.           /* Save original routine address */
  869.        set_dir_adr = set_dir;
  870.           /* Get address of new (user defined) routine  */
  871.        _dos_setvect(INT21, set_dir_adr);
  872.           /* Revector to new service routine */
  873.  
  874.        /* Set trap for PRINT SCREEN interrupt */
  875.        reset_dir_adr = reset_dir;
  876.           /* Get address of new routine */
  877.        _dos_setvect(INT5, reset_dir_adr);
  878.           /* Revector to new routine */
  879.  
  880.        /* Blast off into memory and reside until
  881.        power down or CTRL-ALT-DEL */
  882.  
  883.        _dos_keep(0, _get_memsize());
  884.     }
  885.     else
  886.        puts("problems running DirZap.exe, COMSPEC not found!");
  887.  }
  888.  
  889.  void cdecl interrupt far set_dir(REGPAK)
  890.  {
  891.  
  892.  /*
  893.     Trap directory interrupts MkDir, RmDir, and ChDir and zap the
  894.  string entered by the user. DS:DX points to the string, so change it
  895.  to a string of length 0. WARNING: When compiled at high warning
  896.  levels, several warnings are generated. This is because several
  897.  elements of REGPAK are not referenced. These warnings should be
  898.  ignored.
  899.  */
  900.     if (HIBYTE(ax) == 0x39 || HIBYTE(ax) == 0x3A || HIBYTE(ax) == 0x3B)
  901.        dx=0;
  902.     _chain_intr(save_dir_adr);
  903.  }
  904.  
  905.  void interrupt far reset_dir()
  906.  {
  907.     if (hot_key)
  908.     {
  909.        hot_key=0;
  910.        _dos_setvect(INT21, save_dir_adr); /* Reset initial vector */
  911.  
  912.        }
  913.     else
  914.     {
  915.        hot_key=1;
  916.        _dos_setvect(INT21, set_dir_adr); /* Install DirZap again */
  917.        _chain_intr(set_dir_adr); /* Chain to the Zapper function */
  918.     }
  919.  }
  920.  
  921.  unsigned _get_memsize()
  922.  {
  923.     psp_pointer = (int far *) SHIFTL(_psp, 16); /* Get segment of the PSP*/
  924.     return(psp_pointer[1] - _psp); /* Amount of memory to stay resident */
  925.  }
  926.  
  927.  short _set_shell()
  928.  {
  929.     char *_COMSPEC_;
  930.  
  931.     _COMSPEC_ = getenv("COMSPEC"); /* Get value of COMSPEC */
  932.     if (_COMSPEC_) /* If not equal to NULL */
  933.     {
  934.        puts("type 'EXIT' to invoke DirZapper...");
  935.        spawnlp(P_WAIT, _COMSPEC_, NULL); /* Invoke Command.com */
  936.        return(1);
  937.     }
  938.     return(0);
  939.  }
  940.  
  941.  
  942.  19. Object Module Format Extensions
  943.  
  944.  Product Version(s): 5.00 5.10
  945.  Operating System:   MS-DOS
  946.  Flags: ENDUSER |
  947.  Last Modified: 17-NOV-1988    ArticleIdent: Q28613
  948.  
  949.  The following are Microsoft extensions to the Intel object module
  950.  format that were incorporated in Versions 5.00 and 5.10 of the C
  951.  compiler. For a complete description of the object module format, you
  952.  can contact Microsoft System Languages Technical Support at (206)
  953.  454-2030 and request the Object Module Format Application Note.
  954.  
  955.  Microsoft OMF Extensions
  956.  
  957.  Local Symbols (C 5.00) -- B4h, B6h, B7h, B8h
  958.  
  959.  There will be three new record types to handle local symbols:
  960.  
  961.  1. LEXTDEF = 0xb4 (180)
  962.     Format is identical to EXTDEF.
  963.  
  964.  2. LPUBDEF = 0xb6 (182) or 0xb7 (183)
  965.     Format is identical to PUBDEF.
  966.  
  967.  3. LCOMDEF = 0xb8 (184)
  968.     Format is identical to COMDEF.
  969.  
  970.  LEXTDEF, LPUBDEF, and LCOMDEF are to be used exactly as EXTDEF,
  971.  PUBDEF, and COMDEF, except that the symbols are not visible outside
  972.  the module where they are defined--for example, C statics.
  973.  
  974.  New OMF Comment -- Class A1h
  975.  
  976.  A comment record with class A1h indicates that the obsolete method of
  977.  communal representation through TYPDEF and EXTDEF pairs is not used,
  978.  and that COMDEF records can be interpreted. The meaning of this record
  979.  is undergoing revision.
  980.  
  981.  IMPDEF (OS2, Windows) -- Comment Class A0h, Subtype 1
  982.  
  983.  The IMPort DEFinition (IMPDEF) record takes the form of a COMENT
  984.  record with class 0xa0:
  985.  
  986.      DB      88h         ; COMENT
  987.      DW      reclen      ; record length
  988.      DB      00h         ; for Intel compatibility
  989.      DB      A0h         ; class: OMF extension
  990.      DB      01h         ; subtype: IMPDEF
  991.      DB      fOrd        ; nonzero value means import by ordinal
  992.      ; Internal Name
  993.      DB      n           ; length of name
  994.      DB      n dup(?)    ; ASCII text of name
  995.      ; Module Name
  996.      DB      n           ; length of name
  997.      DB      n dup(?)    ; ASCII text of name
  998.  IF import by name (fOrd == 0)
  999.      ;   Imported Name:  if length byte is 0 then imported name is
  1000.      ;   identical to internal name.
  1001.      ;
  1002.      DB      n           ; length of name
  1003.      DB      n dup(?)    ; ASCII text of name
  1004.  ELSE
  1005.      DW      ordno       ; ordinal number
  1006.  ENDIF
  1007.  
  1008.      DB      checksum
  1009.  
  1010.  EXPDEF (C 5.10) -- Comment Class A0h, Subtype 2
  1011.  
  1012.  The EXPort DEFinition record takes the form of a COMENT record with
  1013.  class 0xa0:
  1014.  
  1015.      DB      88h         ; COMENT
  1016.      DW      reclen      ; record length
  1017.      DB      00h         ; for Intel compatibility
  1018.      DB      A0h         ; class: OMF extension
  1019.      DB      02h         ; extension type:  EXPDEF
  1020.      DB      flags
  1021.          ;   80h = set if ordinal number specified
  1022.          ;   40h = set if RESIDENTNAME
  1023.          ;   20h = set if NODATA
  1024.          ;   1Fh = # of parameter words
  1025.  
  1026.      ; Exported name:
  1027.      DB      n           ; length of name
  1028.      DB      n dup(?)    ; ASCII text of name
  1029.  
  1030.      ; IF internal name different from exported name:
  1031.      DB      n           ; length of name
  1032.      DB      n dup(?)    ; ASCII text of name
  1033.      ; ELSE internal name same as exported name:
  1034.      DB      00h
  1035.  
  1036.      ; IF ordinal number specified
  1037.      DW      ordno       ; ordinal number
  1038.  
  1039.      DB      checksum
  1040.  
  1041.  LIBMOD Comment Record -- Class A3h (LIB 3.07 in MASM 5.00)
  1042.  
  1043.      DB      88h             ; COMENT
  1044.      DW      reclen          ; record length
  1045.      DB      00h             ; for Intel compatibility
  1046.      DB      A3h             ; class: LIBrary MODule name
  1047.      DB      N               ; length of module name
  1048.      DB      N dup(?)        ; ASCII text of module name
  1049.      DB      checksum
  1050.  
  1051.  The LIBMOD comment record identifies the name of a library module.
  1052.  This record allows LIB to preserve the source file name in the THEADR
  1053.  record and still identify the module name. Since the module name is
  1054.  the base name of the .OBJ file, the two names may be completely
  1055.  different.
  1056.  
  1057.  LIB adds a LIBMOD record when an .OBJ file is added to a library and
  1058.  strips the LIBMOD record when an .OBJ file is removed from a library,
  1059.  so this record usually only exists in .LIB files.
  1060.  
  1061.  
  1062.  20. Building C 5.10 Combined Libraries with the LIB Utility
  1063.  
  1064.  Product Version(s): 5.10
  1065.  Operating System:   MS-DOS
  1066.  Flags: ENDUSER |
  1067.  Last Modified: 15-JAN-1991    ArticleIdent: Q28774
  1068.  
  1069.  Question:
  1070.  
  1071.  How does one go about building the combined libraries for C 5.10?
  1072.  
  1073.  Response:
  1074.  
  1075.  The preferred method for building the combined libraries is to use the
  1076.  SETUP program. To use SETUP to build libraries, you can run it with /L
  1077.  as a command-line parameter by typing the following
  1078.  
  1079.     a:setup /L
  1080.  
  1081.  at the DOS prompt with the SETUP disk in the drive A.
  1082.  
  1083.  If you have problems running the Setup program or you want to build
  1084.  the libraries manually using the LIB utility, you should build them as
  1085.  outlined in the following:
  1086.  
  1087.  1. Copy the appropriate library files to your hard disk. The memory
  1088.     model and floating-point option that you want to build will
  1089.     determine which library files are necessary. Refer to the file
  1090.     PACKING.LST to determine where each library file is located.
  1091.  
  1092.  2. Locate the LIB.EXE utility so that it is in your current directory
  1093.     or is located on your path.
  1094.  
  1095.  3. The details for how each library should be built are outlined
  1096.     below. These instructions assume that you will be using the default
  1097.     names for the real-mode libraries. The instructions also assume
  1098.     that you want graphics support built into your real-mode libraries
  1099.     (the graphics routines are not supported in protect mode). If this
  1100.     is not the case, do not include that library.
  1101.  
  1102.  The library name should be the command-line parameter to LIB.EXE. The
  1103.  question mark (?) is used to represent memory model (S, M, C, L) and
  1104.  you should substitute the appropriate letter when invoking the library
  1105.  manager. If you see the following prompt
  1106.  
  1107.     Library does not exist.  Create?
  1108.  
  1109.  you should respond with "y" to create the library and then provide the
  1110.  appropriate libraries at the next prompt which will be the
  1111.  "Operations:" prompt.
  1112.  
  1113.  The following is an example session:
  1114.  
  1115.  Assume that you want to build the small model emulator math library
  1116.  for real mode. This is how you would proceed from the DOS prompt
  1117.  assuming that you have already copied the correct component libraries
  1118.  to the following current directory:
  1119.  
  1120.  >lib slibce
  1121.  
  1122.  Microsoft (R) Library Manager  Version 3.08
  1123.  Copyright (C) Microsoft Corp 1983-1987.  All rights reserved.
  1124.  
  1125.  Library does not exist.  Create?y
  1126.  Operations:slibc.lib+libh.lib+em.lib+libfp.lib+graphics.lib;
  1127.  ---------------
  1128.  
  1129.  Here are the combine instructions for all combinations of the
  1130.  libraries:
  1131.  ---------------
  1132.  
  1133.  ?LIBCE.LIB-Real Mode mode emulator (?==S,M,C or L)
  1134.  
  1135.  Operations:?libc.lib+libh.lib+em.lib+?libfp.lib+graphics.lib;
  1136.  ---------------
  1137.  
  1138.  ?LIBCA.LIB-Real mode alternate math (?==S,M,C or L)
  1139.  
  1140.  Operations:?libc.lib+libh.lib+?libfa.lib+graphics.lib;
  1141.  ---------------
  1142.  
  1143.  ?LIBC7.LIB-Real mode 8087 (?==S,M,C or L)
  1144.  
  1145.  Operations:?libc.lib+libh.lib+87.lib+?libfp.lib+graphics.lib;
  1146.  ---------------
  1147.  
  1148.  ?LIBCEP.LIB-Protect mode emulator (?==S,M,C or L)
  1149.  
  1150.  Operations:?libcp.lib+libh.lib+em.lib+?libfp.lib;
  1151.  ---------------
  1152.  
  1153.  ?LIBCAP.LIB-Protect mode alternate math (?==S,M,C or L)
  1154.  
  1155.  Operations:?libcp.lib+libh.lib+?libfa.lib;
  1156.  ---------------
  1157.  
  1158.  ?LIBC7P.LIB-Protect mode 8087 (?==S,M,C or L)
  1159.  
  1160.  Operations:?libcp.lib+libh.lib+87.lib+?libfp.lib;
  1161.  
  1162.  
  1163.  21. Unresolved External on __Clpow with /Oi and /FPa in C 5.xx
  1164.  
  1165.  Product Version(s): 5.00 5.10
  1166.  Operating System:   MS-DOS
  1167.  Flags: ENDUSER |
  1168.  Last Modified: 15-JAN-1991    ArticleIdent: Q29188
  1169.  
  1170.  The C version 5.00 and 5.10 compilers generate an unresolved external
  1171.  reference to __CIpow when the sample program below is compiled with
  1172.  /Oi (or /Ox) and /FPa.
  1173.  
  1174.  Intrinsic optimization (/Oi) and the alternate floating-point option
  1175.  are not compatible and cannot be used together. This restriction is
  1176.  noted in the C 5.10 README.DOC. The maximum optimization that you can
  1177.  use with the alternate floating-point option is /Oalt.
  1178.  
  1179.  Sample Code
  1180.  -----------
  1181.  
  1182.     /* Compile with /Oi and /FPa  */
  1183.  
  1184.     #include <math.h>
  1185.     #include <stdio.h>
  1186.  
  1187.     main()
  1188.     {
  1189.     float  xx, yy;
  1190.     xx = 4.7;
  1191.     yy = 3.9;
  1192.     printf("%f", pow(xx,yy));
  1193.     }
  1194.  
  1195.  
  1196.  22. SORTDEMO.C/ BIND Use and Misuse
  1197.  
  1198.  Product Version(s): 5.10   | 5.10
  1199.  Operating System:   MS-DOS | OS/2
  1200.  Flags: ENDUSER |
  1201.  Last Modified: 17-AUG-1989    ArticleIdent: Q29196
  1202.  
  1203.  The following article discusses a C Compiler Version 5.10 program
  1204.  called SORTDEMO.C, which is similar to the program that comes with
  1205.  QuickBasic Version 4.00.
  1206.  
  1207.  SORTDEMO.C for C Version 5.10 is for OS/2. It has OS/2 VIO, KBD, and
  1208.  DOS calls. If it has been bound, it can run in DOS and real-mode OS/2,
  1209.  as well as protected-mode OS/2.
  1210.  
  1211.  The following information details the correct way to run SORTDEMO.C
  1212.  (for a system targeting DOS):
  1213.  
  1214.     cl /Lp /Zp sortdemo.c
  1215.     bind sortdemo.exe c:\c\lib\doscalls.lib c:\c\lib\api.lib apilmr.obj
  1216.  
  1217.  The following is an example of several incorrect ways, their results,
  1218.  and their problems (for a system targeting DOS):
  1219.  
  1220.  1. Command: cl /Fb /Lp sortdemo.c (/Fb means to bind the application)
  1221.  
  1222.     Result: It links and appears to bind, but it hangs the computer
  1223.     when it runs from DOS.
  1224.  
  1225.     Problem: Apilmr.obj also needs to be bound. It must perform a
  1226.     separate bind.
  1227.  
  1228.  2. Command: cl /Fb /Lp sortdemo.c apilmr.obj
  1229.  
  1230.     Result: It links and appears to bind, but it hangs the computer
  1231.     when it runs from DOS.
  1232.  
  1233.     Problem: Apilmr.obj needs to be bound with the application because
  1234.     the application makes VIO calls and it accesses the near heap.
  1235.  
  1236.     Perform a separate bind (there is no way to bind in apilmr.obj from
  1237.     the cl compile line).
  1238.  
  1239.  3. Command: cl /Lp sortdemo.c /link doscalls.lib api.lib
  1240.  
  1241.     Result:  The linker gives the error: __acrtused multiply defined
  1242.     error.
  1243.  
  1244.     Problem: You should only link DOSCALLS.LIB. Bind it if it will be
  1245.     used under DOS.
  1246.  
  1247.  4. Command: cl  sortdemo.c
  1248.  
  1249.     Result:  The linker gives 13 unresolved externals, such as
  1250.     KBDCHARIN, VIO* and DOS*.
  1251.  
  1252.     Problem: SORTDEMO.C is an OS/2 application. The program must be
  1253.     compiled using the /Lp switch, and then bound if it will be used
  1254.     under DOS.
  1255.  
  1256.  5. Command: cl /Lp sortdemo.c or cl /Lp /Zp sortdemo.c
  1257.  
  1258.     Result:  It worked correctly for running under OS/2. To run under
  1259.     DOS, you must Bind it using the following:
  1260.  
  1261.     bind sortdemo.exe c:\c\lib\doscalls.lib c:\c\lib\api.lib apilmr.obj
  1262.  
  1263.  
  1264.  23. Why Pointer Subtraction Gives Signed Results
  1265.  
  1266.  Product Version(s): 3.00 4.00 5.00 5.10
  1267.  Operating System:   MS-DOS
  1268.  Flags: ENDUSER |
  1269.  Last Modified: 14-MAR-1990    ArticleIdent: Q29197
  1270.  
  1271.     Pointer subtraction is performed in signed arithmetic. This can
  1272.  become confusing when the pointers being subtracted are more than 32K
  1273.  apart, because the result becomes a negative number.
  1274.     This is correct behavior for the C language as documented in the
  1275.  "Microsoft C Language Reference Manual" and the ANSI C Draft Proposed
  1276.  Standard.
  1277.  
  1278.     Consider the following code fragment:
  1279.  
  1280.          long size;
  1281.          char *ptr1, *ptr2;
  1282.          if (size < (ptr2 - ptr1))
  1283.            ...
  1284.     If the size is 32000, ptr1 is 0, and ptr2 is 33000, then ptr2 minus
  1285.  ptr1 exceeds the range of a signed value and is therefore negative.
  1286.  The comparison size (ptr2 - ptr1) is false, even though ptr1 and ptr2
  1287.  are 33000 elements apart.
  1288.     This situation is documented on Page 124 of the "Microsoft C
  1289.  Language Reference Manual," (Version 5.00 and Version 5.10) which says
  1290.  the following:
  1291.  
  1292.     "When two pointers are subtracted, the difference is converted to a
  1293.  signed integral value by dividing the difference by the size of a
  1294.  value of the type that the pointers address. The size of the integral
  1295.  value is defined by the type ptrdiff_t in the standard include file
  1296.  stddef.h."
  1297.  
  1298.     This also is documented on Page 3.3.6 of the November 9, 1987,
  1299.  edition of the Draft Proposed ANSI C Standard, which states the
  1300.  following:
  1301.  
  1302.     "The size of the result is implementation-defined, and its type (a
  1303.  signed integral type) is ptrdiff_t defined in the <stddef.h> header.
  1304.  As with any other arithmetic overflow, if the result does not fit in
  1305.  the space provided, the behavior is undefined."
  1306.  
  1307.     If you want to think of these pointers as unsigned quantities, you
  1308.  can typecast them as follows:
  1309.  
  1310.          long size;
  1311.          char *ptr1, *ptr2;
  1312.          if (size < ((unsigned) ptr2 - (unsigned) ptr1))
  1313.            ...
  1314.  
  1315.  
  1316.  24. Incorrect Interface Statement
  1317.  
  1318.  Product Version(s): 5.00 5.10 | 5.10
  1319.  Operating System:   MS-DOS    | OS/2
  1320.  Flags: ENDUSER | docerr
  1321.  Last Modified: 12-OCT-1988    ArticleIdent: Q29589
  1322.  
  1323.  The last example on Page 48 of the "Microsoft C 5.1 Optimizing
  1324.  Compiler Mixed-Language Programming Guide" reads as follows:
  1325.  
  1326.  INTERFACE TO FUNCTION REAL*8 CFUN [C] (I,J)
  1327.  
  1328.  This is incorrect. It should read as follows:
  1329.  
  1330.  INTERFACE TO REAL*8 FUNCTION CFUN [C] (I,J)
  1331.  
  1332.  
  1333.  25. Structure Packing: /Zp4 or #pragma pack(4), and /Zp2
  1334.  
  1335.  Product Version(s): 5.00 5.10 | 5.10
  1336.  Operating System:   MS-DOS    | OS/2
  1337.  Flags: ENDUSER | docerr
  1338.  Last Modified: 12-OCT-1988    ArticleIdent: Q29825
  1339.  
  1340.  The /Zp4 compiler option or #pragma pack(4) results in a more
  1341.  efficient use of space than indicated on Pages 100 to 102 in both the
  1342.  "Microsoft C 5.00 Optimizing Compiler User's Guide" and the "Microsoft
  1343.  C 5.10 Optimizing Compiler User's Guide." When the C compiler aligns
  1344.  structure members, it uses the /Zp4 or #pragma pack(4) (or /Zp2 or
  1345.  #pragma pack(2) values) as the maximum number of bytes for alignment,
  1346.  but will word (even-byte) align individual struct members whose size
  1347.  is one or two bytes. Contiguous char or array of char members that are
  1348.  immediately preceded by char members will be byte aligned.
  1349.  
  1350.  When specifying 4-byte (or 2-byte) boundaries for aligning structure
  1351.  members, the actual alignment is dependent on the size of the structure
  1352.  member. To avoid wasting space, the compiler will word align structure
  1353.  members that are one or two bytes in size. Structure members whose size
  1354.  is four or eight bytes or greater will be aligned on 4-byte boundaries
  1355.  with the /Zp4 switch or #pragma pack(4) as documented.
  1356.  
  1357.  Char or array of char struct members will be byte aligned if they are
  1358.  preceded by a char struct member, otherwise they will be word aligned.
  1359.  (Search on "Zp" and "char" to find articles with more information on
  1360.  the alignment of char struct members.)
  1361.  
  1362.  The sizeof operator correctly indicates the actual size of the
  1363.  structure with any alignment of struct members.
  1364.  
  1365.  Note that this struct member alignment is different than that which
  1366.  occurred with previous versions of Microsoft C compilers. If using
  1367.  object files containing structures produced by C 4.00 or earlier
  1368.  compiler versions, it may be necessary to use dummy bytes to word
  1369.  align contiguous char struct members.
  1370.  
  1371.  To gain complete control over the alignment of struct members, you may
  1372.  use the /Zp or /Zp1 compiler options, or #pragma pack(1), and pad your
  1373.  struct with an appropriate number of dummy char or array of char
  1374.  members.
  1375.  
  1376.  
  1377.  26. C 5.10 MTDYNA.DOC File: Single-Thread Dynamic-Link Libraries
  1378.  
  1379.  Product Version(s): 5.10   | 5.10
  1380.  Operating System:   MS-DOS | OS/2
  1381.  Flags: ENDUSER |
  1382.  Last Modified: 18-AUG-1989    ArticleIdent: Q29826
  1383.  
  1384.     The following information is from "Section 5: Creating Dynamic-Link
  1385.  Libraries" of the Microsoft C Version 5.10 MTDYNA.DOC file.
  1386.  
  1387.  5.1   Single-Thread Dynamic-Link Libraries
  1388.     The OS/2 support library, LLIBCDLL.LIB, is a large-model,
  1389.  single-thread  C run-time library for creating dynamic-link
  1390.  libraries. This support library is statically linked and uses only the
  1391.  alternate math library.
  1392.     To make the dynamic-link library independent of the program that
  1393.  calls it, the dynamic-link library must preserve the floating-point
  1394.  state and the status of the 80286 CPU registers. This is not possible
  1395.  with the emulator floating-point library, since it takes over the 287
  1396.  chip. However, math done with the alternate math library is done
  1397.  entirely with the 80286 registers. Since the status of the registers
  1398.  is preserved, the alternate math package fits the requirement for the
  1399.  single-thread dynamic-link library.
  1400.     The LLIBCDLL.LIB C OS/2 support library is not reentrant, and so
  1401.  only one thread per process may be executing in it. When creating a
  1402.  single-thread dynamic-link library, you should ensure that only one
  1403.  thread per process is ever executing in the C run-time library.
  1404.     A dynamic-link library written with LLIBCDLL.LIB can handle
  1405.  multiple threads within a process only by explicit serialization using
  1406.  semaphores or some similar mechanism to ensure that only one thread
  1407.  per process is executing in the C run-time library. In all cases the C
  1408.  run-time initialization code must be executed at program startup. This
  1409.  is normally done through the per-process automatic initialization
  1410.  mechanism provided to OS/2 dynamic-link libraries.
  1411.     Dynamic-link libraries created with this library must be linked
  1412.  with LLIBCDLL.LIB and DOSCALLS.LIB only. No other libraries should be
  1413.  used when linking.
  1414.     NOTE: This restriction on library use means that the compiler
  1415.  option /Lp must not be used with LLIBCDLL.LIB. If you are building
  1416.  objects for use with LLIBCDLL.LIB, you should use compiler option /Zl
  1417.  to suppress default-library search records in the object file. If
  1418.  not, you then MUST link with /NOD so that you do not get a default
  1419.  library (such as SLIBCE.LIB) linked in as well.
  1420.     This model uses the C register convention where AX, BX, CX, DX and
  1421.  ES are scratch registers. The direction flag is always assumed to be
  1422.  cleared ("up").
  1423.     The signal function is supported only for the SIGFPE signal. This
  1424.  floating-point exception is not a true signal, but is more like an
  1425.  exception.
  1426.     The DosSetSigHandler OS/2 API call should only be used with great
  1427.  caution since it can "steal" signals from the user program thereby
  1428.  causing problems in this environment.
  1429.  
  1430.  Editor's Note: The information above applies to single-thread DLL's
  1431.  linked with LLIBCDLL.LIB only. Multi-thread .EXE's built with
  1432.  LLIBCMT.LIB, or multi-thread DLL's that dynamically link to CRTLIB.DLL
  1433.  use emulator math only, and will use a coprocessor if it is present.
  1434.  
  1435.  
  1436.  
  1437.  27. C 5.10 MTDYNA.DOC: Threads
  1438.  
  1439.  Product Version(s): 5.10   | 5.10
  1440.  Operating System:   MS-DOS | OS/2
  1441.  Flags: ENDUSER |
  1442.  Last Modified: 15-JAN-1991    ArticleIdent: Q29830
  1443.  
  1444.  The following information is from "Section 1: Introduction" of the
  1445.  Microsoft C version 5.10 MTDYNA.DOC file.
  1446.  
  1447.  1.1   Threads
  1448.  
  1449.  Three types of multitasking are present in OS/2: screen groups,
  1450.  processes, and threads. A screen group, the highest-level multitasking
  1451.  element, consists of one or more processes that share a logical screen
  1452.  and keyboard. For example, a word processor and a database operating
  1453.  simultaneously under OS/2 would represent two screen groups. A process
  1454.  is the part of an executing program that is the unit of ownership for
  1455.  resources such as memory, open files, and semaphores. Finally, a
  1456.  thread is the execution path within a process, and it is the smallest
  1457.  multitasking unit managed by OS/2. A process may consist of one or
  1458.  more threads.
  1459.  
  1460.  Two sample programs supplied with this release highlight the use of
  1461.  threads. The first example program, mhello.c, is a multiple-thread
  1462.  version of the classic "Hello world" program. The second example
  1463.  program, snap.c, uses multiple threads to capture screen images to a
  1464.  file.
  1465.  
  1466.  A pictorial representation of screen groups, processes, and threads is
  1467.  shown in Figure 1 below. Each screen group consists of two processes.
  1468.  These processes are composed of several threads. In any process,
  1469.  thread 1 is the main thread. All threads in a process are independent.
  1470.  
  1471.  Figure 1. Screen Groups, Processes, and Threads
  1472.  
  1473.  +============================================================================
  1474.  |
  1475.  |                                    OS/2
  1476.  |
  1477.  | +----------------------------------+  +----------------------------------+
  1478.  | |          Screen Group 1          |  |          Screen Group 2          |
  1479.  | | +------------+    +------------+ |  | +------------+    +------------+ |
  1480.  | | |  Process 1 |    |  Process 2 | |  | |  Process 1 |    |  Process 2 | |
  1481.  | | |            |    |            | |  | |            |    |            | |
  1482.  | | | *Thread 1* |    |            | |  | | *Thread 1* |    |  *Thread 1*| |
  1483.  | | |            |    | *Thread 1* | |  | | *Thread 2* |    |            | |
  1484.  | | | *Thread 2* |    |            | |  | | *Thread 3* |    |  *Thread 2*| |
  1485.  | | |            |    |            | |  | |            |    |            | |
  1486.  | | +------------+    +------------+ |  | +------------+    +------------+ |
  1487.  | |                                  |  |                                  |
  1488.  | +----------------------------------+  +----------------------------------+
  1489.  |
  1490.  +============================================================================
  1491.  
  1492.  
  1493.  28. C 5.10 MTDYNA.DOC: Dynamic-Link Libraries
  1494.  
  1495.  Product Version(s): 5.10   | 5.10
  1496.  Operating System:   MS-DOS | OS/2
  1497.  Flags: ENDUSER |
  1498.  Last Modified: 15-JAN-1991    ArticleIdent: Q29832
  1499.  
  1500.  The following information is from "Section 1: Introduction" of the
  1501.  Microsoft C version 5.10 MTDYNA.DOC file.
  1502.  
  1503.  1.2   Dynamic-Link Libraries
  1504.  
  1505.  A dynamic-link library is a set of routines that are linked with the
  1506.  program at either load time or run time rather than at the time of
  1507.  compilation.
  1508.  
  1509.  The easiest way to understand dynamic linking is to contrast it with
  1510.  the more familiar method of static linking.
  1511.  
  1512.  Static linking involves the following steps:
  1513.  
  1514.  1. Write and compile a program that calls routines (such as the
  1515.     printf() function) not in the source file. This produces an object
  1516.     file that contains a reference to the external printf() function.
  1517.  
  1518.  2. Link the object file with a library file containing the external
  1519.     function. This linking step combines the two files by including the
  1520.     code for the printf() function into the final executable file. In
  1521.     other words, the reference to printf() is resolved at link time.
  1522.  
  1523.  3. Run the executable file from step 2. This executable file is
  1524.     totally self contained (since it contains the code for the external
  1525.     function).
  1526.  
  1527.  Static linking is useful, but it has the following disadvantages:
  1528.  
  1529.  1. The finale executable code cannot be upgraded or changed without
  1530.     relinking to the main program's object files. In the commercial
  1531.     realm this means that a new release of a program requires that the
  1532.     entire executable file be replaced with a new version.
  1533.  
  1534.  2. Common sets of code cannot be shared. Any and all executable files
  1535.     that use the printf() function must explicitly link in this
  1536.     function. Thus, the code for printf()may be duplicated in many
  1537.     different executable files on a disk or in memory.
  1538.  
  1539.  Dynamic linking, on the other hand, involves the following general
  1540.  steps (the complete process is detailed in Section 5.0 below):
  1541.  
  1542.  1. Write and compile a program that references an external function,
  1543.     just as you do for static linking.
  1544.  
  1545.  2. Create a special definition file (.DEF extension) that specifies
  1546.     which functions the main program will import from the dynamic-link
  1547.     library.
  1548.  
  1549.  3. Link the main program with the appropriate dynamic-link library
  1550.     support library to produce an executable file. This file contains a
  1551.     reference to the external function in the dynamic-link library.
  1552.     This file does NOT contain any code from the external function.
  1553.  
  1554.  4. Create a dynamic-link library that contains the code referenced in
  1555.     the main program.
  1556.  
  1557.  5. Execute the program created in step 3. When this executable file is
  1558.     run, OS/2 loads the code and discovers the special reference to the
  1559.     dynamic-link library. For each external dynamic-link-library
  1560.     reference, OS/2 searches the dynamic-link-library directory and
  1561.     resolves the external reference at load time.
  1562.  
  1563.  The process of dynamic linking has the following advantages:
  1564.  
  1565.  1. An executable file is smaller since it does not contain the code
  1566.     for external functions.
  1567.  
  1568.  2. A program can be upgraded by supplying a new version of the
  1569.     dynamic-link library without relinking the executable file.
  1570.  
  1571.  3. Code may be shared between executable files. A common set of
  1572.     routines can be placed in a dynamic-link library and accessed by
  1573.     any number of executable files. In fact, the OS/2 operating system
  1574.     itself is a dynamic-link library. All of the OS/2 system functions
  1575.     are presented as external procedures that a user program can call.
  1576.  
  1577.  4. Linking is faster.
  1578.  
  1579.  
  1580.  29. C 5.10 MTDYNA.DOC: Multiple-Thread Programs
  1581.  
  1582.  Product Version(s): 5.10   | 5.10
  1583.  Operating System:   MS-DOS | OS/2
  1584.  Flags: ENDUSER |
  1585.  Last Modified: 10-DEC-1990    ArticleIdent: Q29833
  1586.  
  1587.  The following information is from "Section 2: Multiple-Thread
  1588.  Programs" of the Microsoft C version 5.10 MTDYNA.DOC file.
  1589.  
  1590.  Multiple-Thread Programs
  1591.  ------------------------
  1592.  
  1593.  The simplest multiple-thread program is an independent self-contained
  1594.  program that is created by the static linking method.
  1595.  
  1596.  The support library LLIBCMT.LIB is a large-model library that supports
  1597.  the creation of multiple-thread programs. A multiple-thread program
  1598.  created with this library can be any memory model although all calls
  1599.  to the C run-time library must use the large-model calling interface.
  1600.  In other words, all pointers must be far.
  1601.  
  1602.  NOTE: The support library library LLIBCMT.LIB is a large model
  1603.  library. If you want to use pointers returned by the C run-time
  1604.  library, you must use the far keyword in the declaration of your
  1605.  variables. For example, if you want to call fopen(), you would need to
  1606.  say:
  1607.  
  1608.                  FILE far * fp;
  1609.                  fp = fopen (...);
  1610.  
  1611.  This C run-time library is used to create a program that is entirely
  1612.  self contained and that does not share C run-time code or data with
  1613.  any other programs or dynamic-link libraries.
  1614.  
  1615.  A multiple-thread program that uses this library must be linked with
  1616.  only LLIBCMT.LIB and DOSCALLS.LIB. No other C run-time libraries
  1617.  should be used in linking.
  1618.  
  1619.  NOTE: This restriction on library use means that the compiler option
  1620.  /Lp must not be used with LLIBCMT.LIB. If you are building objects for
  1621.  use with LLIBCMT.LIB, you should use compiler option /Zl to suppress
  1622.  default library search records in the object file. If not, you then
  1623.  must link with /NOD (/NODEFAULTLIBRARYSEARCH) so that you do not get a
  1624.  default library (such as SLIBCE.LIB) linked in as well.
  1625.  
  1626.  Programs created for this simple multiple-thread environment should
  1627.  use the special include files provided for this purpose. These files
  1628.  are normally stored in the MT subdirectory of your normal include
  1629.  directory and the constituent .h files have the same name as their
  1630.  regular C run-time counterparts.
  1631.  
  1632.  These special include files should only be used for creating
  1633.  multiple-thread programs. If the regular (that is, the include files
  1634.  in the \INCLUDE subdirectory) are used, multiple-thread programs will
  1635.  not work. Conversely, the multiple-thread include files should not be
  1636.  used to create nonthreaded C programs.
  1637.  
  1638.  Threads are managed in a multiple-thread program by the C functions
  1639.  _beginthread() and _endthread(). A description of these two functions
  1640.  is given below in Section 3.0. The OS/2 Applications Program Interface
  1641.  (API) call DosCreateThread should not be used. If the low-level API
  1642.  calls (DosCreateThread and DosExit) are used, the results are
  1643.  unpredictable.
  1644.  
  1645.  In a multiple-thread program, stack checking is done for each thread.
  1646.  
  1647.  Signal handling is complicated in a multiple-thread environment. In a
  1648.  multiple-thread environment, the C run-time function signal is not
  1649.  supported. Since OS/2 always gives thread 1 control when a signal is
  1650.  handled, thread 1 must not be executing in the C run-time library code
  1651.  when a signal is received. If this precaution is not followed, the
  1652.  possibility of deadlock arises. A deadlock occurs if a thread is
  1653.  waiting for a particular event that does not occur.
  1654.  
  1655.  Signal handling is managed in a multiple-thread environment by using
  1656.  the OS/2 API call DosSetSigHandler with the following restrictions:
  1657.  
  1658.  1. Thread 1 should be dedicated to signal handling and this thread
  1659.     should not call the C run-time library. When a signal is detected
  1660.     by thread 1, some type of semaphore or flag that will be polled
  1661.     from the other threads in the program should be set.
  1662.  
  1663.  2. The other threads check the status of semaphores set by thread 1
  1664.     and respond accordingly.
  1665.  
  1666.  
  1667.  30. C 5.10 MTDYNA.DOC: Sample MT Program/Description of Operation
  1668.  
  1669.  Product Version(s): 5.10   | 5.10
  1670.  Operating System:   MS-DOS | OS/2
  1671.  Flags: ENDUSER |
  1672.  Last Modified: 15-JAN-1991    ArticleIdent: Q29835
  1673.  
  1674.  The following information is from "Section 4: Sample Multiple-Thread C
  1675.  Program" of the Microsoft C version 5.10 MTDYNA.DOC file.
  1676.  
  1677.  Sample Multiple-Thread C Program
  1678.  --------------------------------
  1679.  
  1680.  The subsections below describe the creation and operation of a
  1681.  multiple-thread version of the classic "Hello world" program.
  1682.  
  1683.  4.1   Description of operation
  1684.  
  1685.  The multiple-thread "Hello world" program brings up one thread for
  1686.  each command-line argument. Each thread will print "Hello world from
  1687.  thread <n>!" the number of times specified in the corresponding
  1688.  argument. The maximum number of threads supported in the
  1689.  multiple-thread library is 32.
  1690.  
  1691.  To use it, type
  1692.  
  1693.     mhello <arg1> <arg2> ... <up to 31 args>
  1694.  
  1695.  For example,
  1696.  
  1697.     mhello 2 4 6
  1698.  
  1699.  brings up 3 threads; the first thread says hello 2 times, the second
  1700.  thread says hello 4 times, the third thread says hello 6 times.
  1701.  
  1702.  In operation, the program works as follows:
  1703.  
  1704.  1. Brings up the requested number of threads with _beginthread
  1705.  
  1706.  2. Waits until all threads have been brought up
  1707.  
  1708.  3. Begins multiple-thread execution and waits for completion
  1709.  
  1710.  The explicit synchronization (by means of the flag variable
  1711.  Synchronize) is required because of the small time spent in the child
  1712.  code. Without this synchronization, all threads would begin as thread
  1713.  2. This occurs because the first spawned thread completes execution
  1714.  before the next request to create a thread is acted upon. The time
  1715.  slice allotted to any of the threads is much larger than the execution
  1716.  time spent in each thread. To get around this, bring up all of the
  1717.  threads and then simultaneously start them.
  1718.  
  1719.  An alternative method of synchronization between threads is to use
  1720.  semaphores. A semaphore is a software flag used to coordinate the
  1721.  activities of two or more threads. The use of semaphores for thread
  1722.  control is illustrated in the sample program, snap.c, which is
  1723.  included with this release.
  1724.  
  1725.  Using semaphores is a more elegant and efficient means of
  1726.  synchronizing threads. The DosSleep function causes threads to
  1727.  periodically wake up and check a flag, and thus, the following can
  1728.  occur:
  1729.  
  1730.  1. The thread wakes up when it doesn't have to and performs some
  1731.     processing only to find out it has to go to sleep again.
  1732.  
  1733.  2. The thread sleeps longer than it has to (i.e., the event it's
  1734.     waiting for has already occurred, but the thread is still sleeping
  1735.     until the sleep request expires).
  1736.  
  1737.  Programs should generally use semaphores, particularly when the wait
  1738.  time is non deterministic and potentially long (or forever).
  1739.  
  1740.  For the mhello.c example program, the use of DosSleep is appropriate
  1741.  for the following reasons:
  1742.  
  1743.  1. DosSleep is easily understood and has self-evident functionality.
  1744.  
  1745.  2. The program is not particularly time dependent, and the above two
  1746.     disadvantages will not hurt. Also, we know that this is a one time
  1747.     event, and that main code "quickly" wakes up the child-code portion
  1748.     of the program. That is, the DosSleep code path occurs once at
  1749.     start-up time and is never entered again during child execution.
  1750.  
  1751.     Also, the sleep time is short and deterministic. That is, we know
  1752.     the parent code sets the flag as soon as all the threads have been
  1753.     started. In other words, there is no chance for the parent code to
  1754.     do other things and leave the thread waiting for DosSleep for long
  1755.     periods of time.
  1756.  
  1757.  
  1758.  31. C 5.10 MTDYNA.DOC: Sample MT Program/Compiling and Linking
  1759.  
  1760.  Product Version(s): 5.10   | 5.10
  1761.  Operating System:   MS-DOS | OS/2
  1762.  Flags: ENDUSER |
  1763.  Last Modified: 15-JAN-1991    ArticleIdent: Q29836
  1764.  
  1765.  The following information is from "Section 4: Sample Multiple-Thread C
  1766.  Program" of the Microsoft C version 5.10 MTDYNA.DOC file.
  1767.  
  1768.  4.2   Compiling and Linking a Multiple-Thread Program
  1769.  
  1770.  The program mhello.c is a statically linked multiple-thread program.
  1771.  The process of compiling and linking this program is given below:
  1772.  
  1773.  1. Ensure that the files LLIBCMT.LIB and DOSCALLS.LIB are available.
  1774.  
  1775.     The file LLIBCMT.LIB takes the place of the regular *.LIB files
  1776.     used in linking. It is a large-model library that supports the
  1777.     creation of statically linked multiple-thread programs. A
  1778.     multiple-thread program created with this library can be any memory
  1779.     model, although all calls to the C run-time library must use the
  1780.     large-model calling interface.
  1781.  
  1782.     The file DOSCALLS.LIB provides support for any OS/2 calls made in
  1783.     the multiple-thread program. In this example, the DosSleep function
  1784.     is used.
  1785.  
  1786.  2. Ensure that the special multiple-thread include files are used.
  1787.     These are normally stored in the MT subdirectory of the normal
  1788.     \INCLUDE directory. In this example, this is done by explicitly
  1789.     specifying them within the mhello.c program as shown below:
  1790.  
  1791.        #include <mt\malloc.h>
  1792.  
  1793.     The multiple-thread files may also be specified by using the \I
  1794.     option on the CL command line. The multiple-thread dynamic-link
  1795.     library example (Section 5.2.3) uses this method to specify an
  1796.     alternate include directory path.
  1797.  
  1798.  3. Compile the program with the following conditions set:
  1799.  
  1800.     a. Large code-pointer size
  1801.     b. Far data-pointer size
  1802.     c. Segment setup of SS not equal to DS; DS fixed
  1803.  
  1804.     These conditions are specified by setting up a customized memory
  1805.     model using the following CL command option:
  1806.  
  1807.        /Alfw
  1808.  
  1809.     The complete CL invocation is shown below:
  1810.  
  1811.        CL  /Alfw /c  mhello.c
  1812.  
  1813.  4. Link the resulting object file with LLIBCMT.LIB and DOSCALLS.LIB
  1814.     only. The default .LIB file should not be used. Specify the
  1815.     /NODEFAULTLIBRARY search option (/NOD) to ignore the default
  1816.     libraries.
  1817.  
  1818.     The complete LINK invocation is shown below:
  1819.  
  1820.        LINK  /NOD thread LLIBCMT.LIB DOSCALLS.LIB;
  1821.  
  1822.     An alternative invocation that invokes both the compiler and linker
  1823.     is shown below:
  1824.  
  1825.        CL /Alfw /Zl mhello.c /link llibcmt doscalls
  1826.  
  1827.  5. Run the program under OS/2.
  1828.  
  1829.  
  1830.  32. C 5.10 MTDYNA.DOC: Sample MT Program/Possible Problem Areas
  1831.  
  1832.  Product Version(s): 5.10   | 5.10
  1833.  Operating System:   MS-DOS | OS/2
  1834.  Flags: ENDUSER |
  1835.  Last Modified: 15-JAN-1991    ArticleIdent: Q29837
  1836.  
  1837.  The following information is from "Section 4: Sample Multiple-Thread C
  1838.  Program" of the Microsoft C version 5.10 MTDYNA.DOC file.
  1839.  
  1840.  4.3   Possible Problem Areas
  1841.  
  1842.  Several possible problems may occur when creating, linking, or
  1843.  executing a multiple-thread C program. Some of the more common ones
  1844.  are listed below. The symptom is listed first, followed by the likely
  1845.  cause:
  1846.  
  1847.  1. LINK searches for xLIByz.LIB
  1848.  
  1849.     This is caused by omitting the /NOD option from the LINK command.
  1850.     If /NOD is omitted, LINK searches for the default library. The
  1851.     default library should NOT be used with multiple-thread programs.
  1852.     The /NOD option tells the computer not to search the default
  1853.     libraries. This problem may also be avoided by compiling with the
  1854.     /Zl option which suppresses default library search records in the
  1855.     object files.
  1856.  
  1857.  2. You get the following execution error:
  1858.  
  1859.        SYS1943: A program caused a protection violation.
  1860.  
  1861.     This is caused by failing to specify the condition "SS is not equal
  1862.     to DS" in the CL command invocation. Specify the correct conditions
  1863.     with the /Alfw customized memory-model option. Recompile the
  1864.     program with /Alfw.
  1865.  
  1866.  
  1867.  33. C 5.10 MTDYNA.DOC: Creating Dynamic-Link Libraries
  1868.  
  1869.  Product Version(s): 5.10   | 5.10
  1870.  Operating System:   MS-DOS | OS/2
  1871.  Flags: ENDUSER |
  1872.  Last Modified: 15-JAN-1991    ArticleIdent: Q29838
  1873.  
  1874.  The following information is from "Section 5: Creating Dynamic-Link
  1875.  Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
  1876.  
  1877.  Creating Dynamic-Link Libraries
  1878.  
  1879.  You can create the following two types of dynamic-link libraries with
  1880.  this release of C:
  1881.  
  1882.  1. A stand-alone, single-thread dynamic-link library
  1883.  
  1884.  2. A C run-time dynamic-link library that supports multiple threads
  1885.     and is itself dynamically linked.
  1886.  
  1887.  The stand-alone dynamic-link library is independent of the calling
  1888.  program and is single thread only and statically linked. This isolated
  1889.  dynamic-link library is independent of the effects of other
  1890.  dynamic-link libraries and can be viewed conceptually as an extension
  1891.  of the operating system. Use the OS/2 support library, LLIBCDLL.LIB, a
  1892.  large-model, single-thread C run-time library for creating
  1893.  single-thread dynamic-link libraries. LLIBCDLL.LIB is statically
  1894.  linked and uses only the alternate math library.
  1895.  
  1896.  The dynamically-linked C run-time library may be used by a
  1897.  multiple-thread program and an optional group of dynamic-link
  1898.  libraries that are closely associated with it. Use the OS/2 support
  1899.  library, CDLLOBJS.LIB to create a C run-time library that is
  1900.  dynamically linked.
  1901.  
  1902.  Dynamic-link libraries can be debugged with the protected-mode
  1903.  CodeView debugger (CVP). For more information on this topic, see
  1904.  Section 2.2.2 "Debugging Dynamic-Link Modules" in the Microsoft
  1905.  CodeView and Utilities Update document.
  1906.  
  1907.  
  1908.  34. C 5.10 MTDYNA.DOC: Component Files of a Single Thread DLL
  1909.  
  1910.  Product Version(s): 5.10   | 5.10
  1911.  Operating System:   MS-DOS | OS/2
  1912.  Flags: ENDUSER |
  1913.  Last Modified: 15-JAN-1991    ArticleIdent: Q29839
  1914.  
  1915.  The following information is from "Section 5: Creating Dynamic-Link
  1916.  Libraries" of the Microsoft C Version 5.10 MTDYNA.DOC file.
  1917.  
  1918.  5.1.1 Component Files of Single-Thread Dynamic-Link Libraries
  1919.  
  1920.  Several files are supplied for the creation of single-thread
  1921.  dynamic-link libraries. A list and brief description of the files
  1922.  supplied with this release is shown below:
  1923.  
  1924.     DOSCALLS.LIB     OS/2 support library.
  1925.  
  1926.     LLIBCDLL.LIB     Large-model single-thread C run-time library
  1927.                      for dynamic-link library support.
  1928.  
  1929.     xLIByP.LIB       Any protected-mode C run-time library; used to
  1930.                      link sample main program.
  1931.  
  1932.     STMAIN.C         Sample main program (single-thread version).
  1933.     STMAIN.DEF       Module-definition file for main program
  1934.                      (single-thread).
  1935.  
  1936.     STDLL.C          Sample dynamic-link library file.
  1937.     STDLL.DEF        Module-definition file for STDLL.C.
  1938.  
  1939.     MKSTDLL.CMD      OS/2 batch file for creating single-thread
  1940.                      dynamic-link library.
  1941.  
  1942.  
  1943.  35. C 5.10 MTDYNA.DOC: Creating a Single Thread DLL
  1944.  
  1945.  Product Version(s): 5.10   | 5.10
  1946.  Operating System:   MS-DOS | OS/2
  1947.  Flags: ENDUSER |
  1948.  Last Modified: 15-JAN-1991    ArticleIdent: Q29840
  1949.  
  1950.  The following information is from "Section 5: Creating Dynamic-Link
  1951.  Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
  1952.  
  1953.  5.1.2   Creating a Single-Thread Dynamic-Link Library
  1954.  
  1955.  The process of creating a single-thread dynamic-link library is
  1956.  outlined below:
  1957.  
  1958.  1. Create a definition file (.DEF extension) for the main program
  1959.     (STMAIN.DEF). This definition file specifies which functions it
  1960.     will import from the dynamic-link library. In this simple example,
  1961.     the file STMAIN.DEF contains the following:
  1962.  
  1963.        NAME STMAIN
  1964.        IMPORTS STDLL._DynalibTest
  1965.  
  1966.  2. Create a definition file for the dynamic-link library (STDLL.DEF)
  1967.     that specifies which functions it will export. In this simple
  1968.     example, the file STDLL.DEF contains the following:
  1969.  
  1970.        LIBRARY STDLL
  1971.        DESCRIPTION 'Sample Dynamic-Link Library written in Microsoft C'
  1972.        PROTMODE
  1973.        EXPORTS _DynalibTest
  1974.        DATA MULTIPLE
  1975.  
  1976.  3. Compile the main program. The program may be compiled using any
  1977.     memory model and any math package. Since the sample single-thread
  1978.     dynamic-link library (STDLL.C) uses far data, the sample main
  1979.     program (STMAIN.C) can be compiled as either compact or large
  1980.     memory model. For a compact memory model, the C compiler is invoked
  1981.     with something like this:
  1982.  
  1983.        cl /AC /G2 /c stmain.c
  1984.  
  1985.  4. Link the main program to produce STMAIN.EXE. The following files
  1986.     are linked together:
  1987.  
  1988.        STMAIN.OBJ     Output from step 3
  1989.        DOSCALLS.LIB   OS/2 support library
  1990.        CLIBCEP.LIB    Any regular C run-time library (in this
  1991.                       case, compact memory model, emulator math
  1992.                       package)
  1993.        STMAIN.DEF     Main definition-module (single thread)
  1994.        STMAIN.EXE     Output from LINK (single thread)
  1995.  
  1996.     The linker is invoked with something like this:
  1997.  
  1998.        link stmain.obj/noi,,, clibcep.lib doscalls.lib/nod,stmain.def;
  1999.  
  2000.  5. Compile the dynamic-link library module. The module should be
  2001.     compiled with the /ALfw option which specifies large-code pointer
  2002.     size, far-data pointer size and a segment setup of SS not equal to
  2003.     DS; DS fixed. Stack checking should also be turned off. The C
  2004.     compiler is invoked with something like this:
  2005.  
  2006.        cl /Alfw /G2 /Gs /c stdll.c
  2007.  
  2008.  6. Link the dynamic-link library module to produce STDLL.DLL. The
  2009.     following files are linked together:
  2010.  
  2011.        STDLL.OBJ      Output from step 5
  2012.        DOSCALLS.LIB   OS/2 support library
  2013.        LLIBCDLL.LIB   Single-thread dynamic-link library C
  2014.                       run-time support library
  2015.        STDLL.DEF      Dynamic-link library definition-module
  2016.        STDLL.DLL      Output from LINK
  2017.  
  2018.     The linker is invoked with something like this:
  2019.  
  2020.        link stdll.obj,stdll.dll/noi,,llibcdll.lib doscalls.lib/nod,stdll.def;
  2021.  
  2022.  7. Place the STDLL.DLL file (from step 6) in a directory on your
  2023.     LIBPATH so OS/2 is able to find it. Then run the program
  2024.     STMAIN.EXE. If the dynamic-link-library file is not in your
  2025.     LIBPATH, OS/2 is not be able to run STMAIN.EXE.
  2026.  
  2027.  Note: The LIBPATH is set in your CONFIG.SYS or CONFIG.OS2 file,
  2028.  depending on which version of OS/2 you are using. LIBPATH is not part
  2029.  of your environment strings like the LIB, INCLUDE and PATH variables.
  2030.  
  2031.  
  2032.  36. C 5.10 MTDYNA.DOC: Multiple Thread Dynamic-Link libraries
  2033.  
  2034.  Product Version(s): 5.10   | 5.10
  2035.  Operating System:   MS-DOS | OS/2
  2036.  Flags: ENDUSER |
  2037.  Last Modified: 15-JAN-1991    ArticleIdent: Q29841
  2038.  
  2039.  The following information is from "Section 5: Creating Dynamic-Link
  2040.  Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
  2041.  
  2042.  5.2   Multiple-Thread Dynamic-Link Libraries
  2043.  
  2044.  The CDLLOBJS.LIB OS/2 support file is an object-file library used to
  2045.  create a dynamically linked C run-time library. This library is
  2046.  provided as an object library with an associated definition file. This
  2047.  allows the programmer to choose only those run-time modules that are
  2048.  required for a particular application.
  2049.  
  2050.  The C run-time library created with this support file is dynamically
  2051.  linked and may be used by a multiple-thread program and an optional
  2052.  group of dynamic-link libraries that are closely associated with it.
  2053.  
  2054.  The "close association" of the multiple-thread program, the C run-time
  2055.  library and a group of dynamic-link libraries is shown in Figure 2.
  2056.  
  2057.          +----------------------------------------------------+
  2058.          |                                                    |
  2059.          |                +----------+        +----------+    |
  2060.          |                |          |        |          |    |
  2061.          |  +-----------> | DLL1.DLL |<------>| DLL2.DLL |<---+
  2062.          |  |             |          |<-+     |          |<----------+
  2063.          |  |             +----------+  |     +----------+           |
  2064.      +-------------+                    |                            |
  2065.      |             |                    |                            |
  2066.      | PROGRAM.EXE |                    |                            |
  2067.      |             |<---+               |                            |
  2068.      +-------------+    |               |                            |
  2069.                         |               |   +--------------------+   |
  2070.                         |               |   |                    |   |
  2071.                         |               +-->|   C Run-time DLL   |<--+
  2072.                         +------------------>|     CRTLIB.DLL     |
  2073.                                             +--------------------+
  2074.  
  2075.       Figure 2. Relationship between Multiple-Thread Program, C
  2076.                 Run-Time Library, and Dynamic-Link Libraries
  2077.  
  2078.  The main program (PROGRAM.EXE) and the two dynamic-link libraries
  2079.  (DLL1.DLL and DLL2.DLL) share the C run-time data (in CRTLIB.DLL). The
  2080.  PROG.EXE, DLL1.DLL, and DLL2.DLL files each have their own data
  2081.  segment that is not shared. The C run-time dynamic-link library is
  2082.  closely tied to the program (PROGRAM.EXE) and the other dynamic-link
  2083.  libraries (DLL1.DLL and DLL2.DLL), since the file CRTLIB.DLL contains
  2084.  such things as shared environment strings, global C run-time data, and
  2085.  thread identification numbers.
  2086.  
  2087.  A program built using the dynamically linked multiple-thread support
  2088.  of the C run-time library may share the C run-time library with one or
  2089.  more dynamic-link libraries that are closely related to it. C run-time
  2090.  global data (such as the standard I/O package FILE, pointers of
  2091.  buffered I/O, and memory allocated with malloc functions) is shared.
  2092.  This means that the program and the associated dynamic-link libraries
  2093.  must cooperate on the usage of this data.
  2094.  
  2095.  Before compiling any programs using routines from the dynamic-link
  2096.  library's object library CDLLOBJS.LIB, ensure that the MT include
  2097.  files are being used (rather than the standard include files), and
  2098.  that the symbol DLL is defined.
  2099.  
  2100.  If the multiple-thread include files are placed in a subdirectory of
  2101.  the normal INCLUDE directory the following style of include can be
  2102.  used:
  2103.  
  2104.      #include  <mt\stdio.h>       /* multiple-thread version */
  2105.  
  2106.  A better approach is to specify a special search path for include
  2107.  files by using the /I option on the CL command line. In this method,
  2108.  the /I adds the specified directory to the front of the list of
  2109.  directories to be searched for include files. A typical use of the /I
  2110.  option is shown below:
  2111.  
  2112.      cl /I\include\mt /AS /Gs2 /DDLL /c mtmain.c
  2113.  
  2114.  This method has the advantage that the program can refer to <stdio.h>,
  2115.  and the appropriate version can be selected at compile time. This
  2116.  approach is used in the sample programs mtmain.c and mtdll.c. If
  2117.  multiple include paths are required, you can specify them with
  2118.  multiple /I options. The include paths are searched in the order in
  2119.  which they appear on the CL command line.
  2120.  
  2121.  The symbol DLL is used to distinguish between multiple-thread programs
  2122.  using LLIBCMT.LIB (where the symbol DLL is not defined) and programs
  2123.  using the dynamically linked C run-time library (where the symbol DLL
  2124.  is defined), which also supports multiple threads.)  This ensures that
  2125.  the appropriate data references (e.g. stdout) are resolved correctly.
  2126.  The symbol DLL may be defined in one of the ways shown below:
  2127.  
  2128.  1. Compile with the /D option on the CL command line. The use of this
  2129.     option is explained in Section 3.3.9.1 of the Microsoft C
  2130.     Optimizing Compiler User's Guide. The syntax of the /D option is
  2131.  
  2132.        CL  /DDLL myprog.c
  2133.  
  2134.  2. Explicitly define the DLL symbol prior to any other preprocessor
  2135.     directives in your source file. This option is shown below:
  2136.  
  2137.        #define DLL
  2138.        #include < ... >    /* include files as needed */
  2139.  
  2140.  Threads are managed in a dynamic-link library created in this
  2141.  environment by the C functions _beginthread() and _endthread(). The
  2142.  OS/2 API call DosCreateThread should not be used. A description of
  2143.  these two functions is given in Section 3.0.
  2144.  
  2145.  
  2146.  37. C 5.10 MTDYNA.DOC: Component Files of MTDYNA Libraries
  2147.  
  2148.  Product Version(s): 5.10   | 5.10
  2149.  Operating System:   MS-DOS | OS/2
  2150.  Flags: ENDUSER |
  2151.  Last Modified: 15-JAN-1991    ArticleIdent: Q29842
  2152.  
  2153.  The following information is from "Section 5: Creating Dynamic-Link
  2154.  Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
  2155.  
  2156.  5.2.1   Component Files of Multiple-Thread Dynamic-Link Libraries
  2157.  
  2158.  A large number of files are supplied for the creation of
  2159.  multiple-thread dynamic-link libraries. A list and brief description
  2160.  of the files supplied with this release is shown below:
  2161.  
  2162.     CRTDLL.OBJ         Start-up code for dynamic-link library files.
  2163.     CRTEXE.OBJ         Start-up code for executable files.
  2164.     CRTLIB.OBJ         Start-up code for C run-time library.
  2165.  
  2166.     CDLLOBJS.LIB       C run-time library objects.
  2167.     CDLLOBJS.DEF       Module-definition file that contains the entry
  2168.                        points for all C functions.
  2169.     CDLLOBJS.CMD       OS/2 batch file to create multiple-thread C
  2170.                        run-time dynamic-link library.
  2171.  
  2172.     CDLLSUPP.LIB       Supplemental file that contains C run-time
  2173.                        information that cannot be dynamically linked.
  2174.  
  2175.     MTMAIN.C           Sample main program (multiple thread).
  2176.     MTMAIN.DEF         Module-definition file for main (multiple
  2177.                        thread).
  2178.  
  2179.     MTDLL.C            Sample dynamic-link library file (multiple
  2180.                        thread).
  2181.     MTDLL.DEF          Module-definition file for DLL.C (multiple
  2182.                        thread).
  2183.  
  2184.     MKMTDLL.CMD        OS/2 batch file for creating multiple-thread
  2185.                        dynamic-link library.
  2186.  
  2187.  
  2188.  38. C 5.10 MTDYNA.DOC: Creating an MTDYNA Library
  2189.  
  2190.  Product Version(s): 5.10   | 5.10
  2191.  Operating System:   MS-DOS | OS/2
  2192.  Flags: ENDUSER |
  2193.  Last Modified: 15-JAN-1991    ArticleIdent: Q29843
  2194.  
  2195.  The following information is from "Section 5: Creating Dynamic-Link
  2196.  Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
  2197.  
  2198.  5.2.2   Creating a Multiple-Thread Dynamic-Link Library
  2199.  
  2200.  The process of creating a multiple-thread dynamic-link library is
  2201.  outlined below. The process of creating a multiple-thread dynamic-link
  2202.  library is also contained in the file CDLLOBJS.CMD.
  2203.  
  2204.  1. Create a definition file that specifies the exports from the C
  2205.     run-time library for the dynamic-link library. The file
  2206.     CDLLOBJS.DEF, which is included in this release, is a sample
  2207.     definition file that includes all of the C run-time functions
  2208.     currently supported.
  2209.  
  2210.  2. Link the special start-up file CRTLIB.OBJ with CDLLOBJS.LIB,
  2211.     DOSCALLS.LIB, and the definition file (CDLLOBJS.DEF) from step 1.
  2212.     This creates a customized C run-time dynamic-link library file
  2213.     (named CRTLIB.DLL). The following files are linked together:
  2214.  
  2215.        crtlib.obj     Start-up code for library files
  2216.        cdllobjs.lib   C run-time library objects
  2217.        doscalls.lib   OS/2 support library
  2218.        cdllobjs.def   Definition module from step 1
  2219.        crtlib.dll     Output from LINK
  2220.  
  2221.  The command to accomplish this is shown below:
  2222.  
  2223.  link crtlib.obj,crtlib.dll/noi,,cdllobjs.lib doscalls.lib/nod/noe,cdllobjs.de
  2224.  
  2225.  3. Run IMPLIB on the definition file from step 1 to create a
  2226.     customized library file (CRTLIB.LIB) containing the exported
  2227.     functions. The command is shown below:
  2228.  
  2229.        implib crtlib.lib cdllobjs.def
  2230.  
  2231.  4. Use the Microsoft Library Manager (LIB) to append CDLLSUPP.LIB to
  2232.     the customized library created in step 3. The file CDLLSUP.LIB
  2233.     contains a few small routines that cannot be dynamically linked
  2234.     because they are called near. The LIB program automatically creates
  2235.     a back-up file (with a .BAK extension), which can be deleted. The
  2236.     command for this step is shown below:
  2237.  
  2238.        lib crtlib.lib+cdllsupp.lib;
  2239.  
  2240.  
  2241.  39. C 5.10 MTDYNA.DOC: Using an MTDYNA Library
  2242.  
  2243.  Product Version(s): 5.10   | 5.10
  2244.  Operating System:   MS-DOS | OS/2
  2245.  Flags: ENDUSER |
  2246.  Last Modified: 15-JAN-1991    ArticleIdent: Q29844
  2247.  
  2248.  The following information is from "Section 5: Creating Dynamic-Link
  2249.  Libraries" of the Microsoft C version 5.10 MTDYNA.DOC file.
  2250.  
  2251.  5.2.3   Using a Multiple-Thread Dynamic-Link Library
  2252.  
  2253.  Once a C run-time multiple-thread dynamic-link library has been
  2254.  created (Section 5.2.2), it can be used by a program and associated
  2255.  dynamic-link libraries. The process of using this C run-time
  2256.  dynamic-link library is shown below:
  2257.  
  2258.  1. Compile the main program. When creating executable and dynamic-link
  2259.     library files that will use the dynamically linked C run-time
  2260.     library, the C compiler must be called with the multiple-thread
  2261.     versions of the include files. Additionally, stack checking must be
  2262.     turned off if your code is being compiled as small or compact
  2263.     models. Stack checking can only be supported in the dynamically
  2264.     linked C run-time library using far calls (medium/large memory
  2265.     models).  The C compiler is invoked with something like this:
  2266.  
  2267.              cl /I\include\mt /AS /Gs2 /DDLL /c mtmain.c
  2268.  
  2269.     The /Gs option specifies no stack checking. The /DDLL option
  2270.     defines the DLL symbol. The /AS option specifies small memory
  2271.     model. The /I\include\mt option specifies that the special
  2272.     multiple-thread include files are to be used.
  2273.  
  2274.  2. Link the main program to produce MTMAIN.EXE. The following files
  2275.     are linked together:
  2276.  
  2277.        mtmain.obj     Output from step 1
  2278.        crtexe.obj     Start-up code for executable files
  2279.        crtlib.lib     Customized C run-time library (Section 5.2.2)
  2280.        doscalls.lib   OS/2 support library
  2281.        mtmain.def     Definition file for mtmain.c
  2282.        mtmain.exe     Output from LINK
  2283.  
  2284.     The linker is invoked with something like this:
  2285.  
  2286.        link mtmain+crtexe,/noi,,crtlib.lib doscalls.lib/nod,mtmain.def;
  2287.  
  2288.  3. Compile the dynamic-link-library module. When creating executable
  2289.     and dynamic-link library files that will use the dynamically linked
  2290.     C run- time library, the C compiler must be called with the
  2291.     multiple-thread versions of the include files. Additionally, stack
  2292.     checking must be turned off if your code is being compiled as small
  2293.     or compact model. Stack checking can only be supported in the
  2294.     dynamically linked C run-time library using far calls
  2295.     (medium/large memory models.)  The C compiler is invoked with
  2296.     something like this:
  2297.  
  2298.        cl /I\include\mt /Alfw /G2 /DDLL /c mtdll.c
  2299.  
  2300.     The /Alfw option specifies large code-pointer size, far
  2301.     data-pointer size and a segment setup of SS not equal to DS; DS
  2302.     fixed. The /DDLL option defines the DLL symbol. The /I\include\mt
  2303.     option specifies that the special multiple-thread include files are
  2304.     to be used.
  2305.  
  2306.  4. Link the dynamic-link-library module to produce MTDLL.DLL. The
  2307.     following files are linked together:
  2308.  
  2309.        mtdll.obj      Output from step 3
  2310.        crtdll.obj     Start-up code for dynamic-link library files
  2311.        crtlib.lib     Customized C run-time library (Section 5.2.2)
  2312.        doscalls.lib   OS/2 support library
  2313.        mtdll.def      Dynamic-link library definition file
  2314.        mtdll.dll      Output from LINK
  2315.  
  2316.     The linker is invoked with something like this:
  2317.  
  2318.        link mtdll+crtdll,mtdll.dll/noi,,crtlib.lib doscalls.lib/nod,mtdll.def;
  2319.  
  2320.  5. Place the MTDLL.DLL file (from step 4) and the CRTLIB.DLL file
  2321.     (from Section 5.2.2) in a directory on your LIBPATH so OS/2 can
  2322.     find it. Then run the program MTMAIN.EXE. If either dynamic-link
  2323.     library file is not in your LIBPATH, OS/2 will not be able to run
  2324.     MTMAIN.EXE.
  2325.  
  2326.  Note: The LIBPATH is set in your CONFIG.SYS or CONFIG.OS2 file,
  2327.  depending on which version of OS/2 you are using. LIBPATH is not part
  2328.  of your environment strings like the LIB, INCLUDE and PATH variables.
  2329.  
  2330.  
  2331.  40. C 5.10 MTDYNA.DOC: Matrix of Components
  2332.  
  2333.  Product Version(s): 5.10   | 5.10
  2334.  Operating System:   MS-DOS | OS/2
  2335.  Flags: ENDUSER |
  2336.  Last Modified: 15-JAN-1991    ArticleIdent: Q29845
  2337.  
  2338.  The following information is from "Section 6: Matrix of Components" of
  2339.  the Microsoft C version 5.10 MTDYNA.DOC file.
  2340.  
  2341.  Matrix of Components
  2342.  --------------------
  2343.  
  2344.  Table 1 lists the various components needed to create multiple-thread
  2345.  programs and the two types of dynamic-link libraries discussed above.
  2346.  For comparison, a single-thread executable file is also included in
  2347.  the table. (A single-thread executable file is simply a regular C
  2348.  program.)
  2349.  
  2350.  The components have the following meanings:
  2351.  
  2352.     .OBJ            Object files
  2353.  
  2354.     .LIB            Library files
  2355.  
  2356.     .h              Location (default) of include files
  2357.  
  2358.     DLL             Status of DLL symbol (either defined or not defined)
  2359.  
  2360.     xLIBCyP.LIB     Regular C run-time library for protected mode
  2361.                        x = memory model (S, C, M, L)
  2362.                        y = math package (A, E, 7)
  2363.  
  2364.  Table 1.  Output-File Type
  2365.  
  2366.                       Executable                    Dynamic-Link Library
  2367.  
  2368.  Component  Single Thread    Multiple Thread   Single Thread    Multiple Threa
  2369.  ---------  -------------    ---------------   -------------    --------------
  2370.  
  2371.  .OBJ       ...              ...               ...              CRTDLL.OBJ
  2372.                                                                 CRTEXE.OBJ
  2373.                                                                 CRTLIB.OBJ
  2374.  
  2375.  .LIB       xCLIBCyP.LIB     LLIBCMT.LIB       LLIBCDLL.LIB     CDLLOBJS.LIB
  2376.                              DOSCALLS.LIB      DOSCALLS.LIB     CDLLOBJS.DEF
  2377.                                                                 CDLLSUPP.LIB
  2378.                                                                 DOSCALLS.LIB
  2379.  
  2380.  .h         \INCLUDE         \INCLUDE\MT       \INCLUDE         \INCLUDE\MT
  2381.  
  2382.  DLL        Not defined      Not defined       Not defined      Defined
  2383.  
  2384.  
  2385.  41. Appending to CTRL+Z Terminated File with Fopen()
  2386.  
  2387.  Product Version(s): 4.00 5.00 5.10
  2388.  Operating System:   MS-DOS
  2389.  Flags: ENDUSER |
  2390.  Last Modified: 23-SEP-1988    ArticleIdent: Q29852
  2391.  
  2392.  When appending to a stream file that is terminated with the
  2393.  end-of-file marker CTRL+Z (CONTROL+Z or the ASCII code 1A
  2394.  hexadecimal), use the "a+" type with the fopen() function. The "+" in
  2395.  the type "a+" allows for both writing and reading.
  2396.  
  2397.  If you use the "a" type with fopen() for appending in write-only mode,
  2398.  the end-of-file marker will not be removed. Subsequently using the DOS
  2399.  type command on the file will only display data up to the original
  2400.  end-of-file marker, and will not display appended data.
  2401.  
  2402.  The fopen() type "a+" will allow the removal of the end-of-file marker
  2403.  from the file before appending, so that the appended data can then be
  2404.  displayed by the DOS type command.
  2405.  
  2406.  The "a+" is required because DOS must be permitted to read the file to
  2407.  locate the end-of-file marker and overwrite it with appended data.
  2408.  Using the "a" type prohibits DOS from reading the file, so DOS is
  2409.  unable to find the end-of-file marker for overwriting and instead the
  2410.  appended data is written after the end-of-file marker.
  2411.  
  2412.  
  2413.  42. C 5.10 UTILITY.DOC: Microsoft Pascal Programs
  2414.  
  2415.  Product Version(s): 5.10   | 5.10
  2416.  Operating System:   MS-DOS | OS/2
  2417.  Flags: ENDUSER | docerr s_codeview
  2418.  Last Modified: 16-JAN-1991    ArticleIdent: Q29903
  2419.  
  2420.  The following information is from the section titled "Microsoft(R)
  2421.  CodeView(R) Debugger" of the Microsoft C Version 5.10 UTILITY.DOC
  2422.  file.
  2423.  
  2424.  Microsoft Pascal Programs
  2425.  
  2426.  In this release, Microsoft Pascal programs cannot be debugged with
  2427.  the CodeView debugger.
  2428.  
  2429.  The Pascal example on pg. 61 of the Microsoft CodeView and
  2430.  Utilities manual should read
  2431.  
  2432.  PAS1 /Zz TEST;
  2433.  
  2434.  rather than
  2435.  
  2436.  PAS1 /Zi TEST;
  2437.  
  2438.  
  2439.  43. Wild-Card Expansion
  2440.  
  2441.  Product Version(s): 5.10   | 5.10
  2442.  Operating System:   MS-DOS | OS/2
  2443.  Flags: ENDUSER | docerr
  2444.  Last Modified: 12-OCT-1988    ArticleIdent: Q29925
  2445.  
  2446.  Problem:
  2447.  
  2448.  I am attempting to insert the _setargv module into my standard C
  2449.  library to expand wild-card command line arguments as documented on
  2450.  Page 130 of the "Microsoft C 5.10 Optimizing Compiler User's Guide."
  2451.  
  2452.  When I invoke the LIB utility to remove the old _setargv module
  2453.  from the C library, I get the warning message "setargv.obj: warning
  2454.  U4151: '__setargv': symbol defined in module stdargv, redefinition
  2455.  ignored."
  2456.  
  2457.  My program is supposed to expand *.dat and print the names of all .dat
  2458.  files in the current directory. When I link my compiled code to the
  2459.  modified C library, I do not receive any errors. However, when I run
  2460.  my program, it prints out *.dat instead of expanding the wild card.
  2461.  
  2462.  Response:
  2463.  
  2464.  This is an error in documentation. The name of the module that you
  2465.  should extract from the C run-time library is stdargv. To replace this
  2466.  module with the module for expanding wild cards, use the LIB utility
  2467.  and enter the following module names after the Operations: prompt:
  2468.  
  2469.  Operations: -stdargv+setargv
  2470.  
  2471.  After performing this operation with LIB, linking the modified C
  2472.  library to your code will now permit the expansion of wild-card
  2473.  arguments by means of the argv[] array that is one of the main()
  2474.  function arguments.
  2475.  
  2476.  Note that you may link the object file setargv.obj with your code and
  2477.  an unmodified C run-time library to allow the expansion of wild cards.
  2478.  The replacement of module stdargv with setargv.obj allows wild-card
  2479.  expansion without explicitly linking in "setargv.obj" each time.
  2480.  
  2481.  C Version 4.00 and its documentation about the wild-card expansion
  2482.  library module had a similar problem.
  2483.  
  2484.  If you are using C Version 4.00, search for wild card and setargv for
  2485.  more information.
  2486.  
  2487.  
  2488.  44. Reading F11 and F12 Keys on Extended Keyboard
  2489.  
  2490.  Product Version(s): 5.00 5.10
  2491.  Operating System:   MS-DOS
  2492.  Flags: ENDUSER |
  2493.  Last Modified: 11-AUG-1989    ArticleIdent: Q30370
  2494.  
  2495.     The following program will allow you to read the F11 and F12 keys
  2496.  on an extended keyboard. The key to this process is to call
  2497.  _bios_keybrd() with the service argument 0x10. This will allow an
  2498.  extended keyboard read. This program will sit in an infinite loop
  2499.  until F11 or F12 is pressed. Note that the C run-time library
  2500.  functions getch() or getche() will not be able to read in the extended
  2501.  function keys even after the change above has been made.
  2502.  
  2503.  #include <bios.h>
  2504.  #include <stdio.h>
  2505.  #define _EXTKEYREAD 0x10
  2506.  #define MASK 0xFF00
  2507.  #define ZMASK 0x00FF
  2508.  main()
  2509.  {
  2510.    unsigned value, nextval;
  2511.    while(1)
  2512.    {
  2513.    value = _bios_keybrd(_EXTKEYREAD);
  2514.    nextval = value;
  2515.    if ((value & ZMASK) == 0)         /* check low order byte for zero*/
  2516.                                      /* if zero, then we have extended key*/
  2517.      {
  2518.  
  2519.         if((nextval & MASK) == 0x8500)   /* buffer code = 8500h for F11 */
  2520.         printf("F11 key pushed\n");
  2521.  
  2522.         if((nextval & MASK) == 0x8600)   /* buffer code = 8600 for F12 */
  2523.         printf("F12 key pushed\n");
  2524.      }
  2525.    else
  2526.      printf("not an extended key\n");
  2527.  
  2528.    }
  2529.  }
  2530.  
  2531.  
  2532.  
  2533.  45. Trapping FP Execptions with In-Line 8087 Code
  2534.  
  2535.  Product Version(s): 5.00 5.10 | 5.10
  2536.  Operating System:   MS-DOS    | OS/2
  2537.  Flags: ENDUSER | docerr
  2538.  Last Modified: 27-OCT-1988    ArticleIdent: Q30644
  2539.  
  2540.  Problem:
  2541.  
  2542.  I am following the instructions on Pages 167-68 of the "Microsoft C
  2543.  Optimizing Compiler User's Guide" to generate true in-line 8087 code.
  2544.  I can link a module to remove the fixups for the interrupts, but I can
  2545.  no longer handle floating-point exceptions using the signal function.
  2546.  
  2547.  Response:
  2548.  
  2549.  This is a documentation error. To trap floating-point exceptions with
  2550.  the signal function while having true in-line 8087 code, you need to
  2551.  add the following instructions to your FIXUP.ASM module:
  2552.  
  2553.             extrn __fpmath:far
  2554.             extrn __fptaskdata:far
  2555.             extrn __fpsignal:far
  2556.  
  2557.             CDATA   segment word common 'DATA'
  2558.                     dw      0
  2559.                     dd      __fpmath
  2560.                     dd      __fptaskdata
  2561.                     dd      __fpsignal
  2562.             CDATA   ends
  2563.  
  2564.  Without the previous code, the start-up code will not initialize
  2565.  the emulator and the signal function returns an error when you attempt
  2566.  to use signal to trap floating-point exceptions.
  2567.  
  2568.  
  2569.  46. Cannot Create .COM Files in C Compiler
  2570.  
  2571.  Product Version(s): 3.00 4.00 5.00 5.10
  2572.  Operating System:   MS-DOS
  2573.  Flags: ENDUSER |
  2574.  Last Modified: 16-JUN-1988    ArticleIdent: Q30646
  2575.  
  2576.     The Microsoft C Compiler Versions 3.00, 4.00, 5.00, and 5.10 do not
  2577.  support the creation of .COM programs. This is because the smallest
  2578.  memory model that can be created is Small Model, which has one Code
  2579.  segment and one Data segment, while .COM programs can only have one
  2580.  segment.
  2581.  
  2582.     .EXE files are converted to .COM files using the MS-DOS utility
  2583.  EXE2BIN (see your MS-DOS manual and/or Page 51 of Ray Duncan's
  2584.  "Advanced MS-DOS"). The .COM programs cannot contain more than one
  2585.  declared segment; however, the Microsoft C compiler creates segments
  2586.  named _DATA, _TEXT, CONST, _BSS, etc.
  2587.     There are no compiler options to create a "Tiny model" program.
  2588.  For this reason, most .COM programs are written in assembler.
  2589.     One way to use the C Compiler in creating .COM programs is to
  2590.  compile with the /Fa option to create an assembly listing. The .ASM
  2591.  file(s) can then be modified so it only uses one segment.
  2592.  
  2593.  
  2594.  
  2595.  47. Initialization of auto Arrays, Structs, Unions Not Allowed
  2596.  
  2597.  Product Version(s): 4.00 5.00 | 5.10
  2598.  Operating System:   MS-DOS    | OS/2
  2599.  Flags: ENDUSER |
  2600.  Last Modified: 17-AUG-1989    ArticleIdent: Q34668
  2601.  
  2602.  Problem:
  2603.  
  2604.  Both the ANSI draft standard for C (May 1988) and "The C Programming
  2605.  Language," Second Edition (by Kernighan and Ritchie) show that
  2606.  initializing aggregate data items declared with auto storage class is
  2607.  allowed in Standard C; however, our compiler flags fatal errors when
  2608.  such attempts are made.
  2609.  
  2610.  The error message C2073 cannot initialize array if function is issued
  2611.  when attempting to compile an array initilization within a function
  2612.  such as the following:
  2613.  
  2614.  foo() {
  2615.      char array[]="intialized local array will cause an error";
  2616.  }
  2617.  
  2618.  Response:
  2619.  
  2620.  This restriction is stated in the "Microsoft C 5.1 Optimizing Compiler
  2621.  Language Reference" on Page 89.
  2622.  
  2623.  One possible workaround is to use the static storage class rather than
  2624.  auto (auto is the default for declarations inside a function). This
  2625.  process has the advantage of making only one copy of the array and
  2626.  initializing it only ONCE, conceptually at the start of program
  2627.  execution; however, this can be a problem for recursive functions that
  2628.  may need a separate copy of the array for each invocation of the
  2629.  function.
  2630.  
  2631.  Another workaround is to declare two arrays: one static and one auto.
  2632.  Initialize the static array and copy it into the auto array (e.g.
  2633.  using the fast memcpy function) at the beginning of the function. Note
  2634.  that there is no speed or space penalty for this process because the
  2635.  second workaround is basically what the compiler would have to do if
  2636.  it allowed initialization of auto arrays.
  2637.  
  2638.  The first workaround will give a savings of both time and space over
  2639.  both the second workaround and over initializing an auto aggregate.
  2640.  
  2641.  
  2642.  48. chdir() Example Is Incorrect
  2643.  
  2644.  Product Version(s): 5.00 5.10 | 5.10
  2645.  Operating System:   MS-DOS    | OS/2
  2646.  Flags: ENDUSER | docerr
  2647.  Last Modified: 12-OCT-1988    ArticleIdent: Q30959
  2648.  
  2649.  The example of the chdir() function on Page 156 of the "Microsoft C
  2650.  Run-Time Library Reference" manual is incorrect. This example is
  2651.  missing double quotation marks around the path. It should read as
  2652.  follows:
  2653.  
  2654.  chdir("c:\\temp") ;
  2655.  
  2656.  
  2657.  49. Array Index Multiplication with Integers Causes Link Error
  2658.  
  2659.  Product Version(s): 5.00 5.10
  2660.  Operating System:   MS-DOS
  2661.  Flags: ENDUSER | TAR77788
  2662.  Last Modified: 16-JUN-1988    ArticleIdent: Q31448
  2663.  
  2664.     When the following program is compiled and linked, the linker
  2665.  generates the error "L2029 -unresolved external for the variable
  2666.  _arr." However, the array appears to be declared legally. The
  2667.  following code generates the error:
  2668.  
  2669.     char huge arr[256*512];
  2670.     main(){}
  2671.  
  2672.    The problem occurs because the multiplication for the array index is
  2673.  done with integers and the result of the multiplication is too large
  2674.  to fit in an integer. This will result in the array index being 0
  2675.  (zero). Because of this array, the following declaration
  2676.  
  2677.     char huge arr[256*512];
  2678.  
  2679.  is equivalent to the following declaration:
  2680.  
  2681.     char huge arr[0];
  2682.  
  2683.     The second declaration in turn, is equivalent to the following
  2684.  declaration:
  2685.  
  2686.     char huge arr[];
  2687.  
  2688.     This type of declaration will cause the compiler to generate an
  2689.  explicit external reference for the array arr and force the linker to
  2690.  look for the variable arr.
  2691.     To solve this problem, do the multiplication for the array index
  2692.  with long integers by declaring one or both of the integer constants
  2693.  as long. The following is a code example:
  2694.  
  2695.     char huge arr[256L*512];
  2696.  
  2697.  
  2698.  
  2699.  50. README.DOC Refers to Undocumented "Link Options"
  2700.  
  2701.  Product Version(s): 5.10
  2702.  Operating System:   MS-DOS
  2703.  Flags: ENDUSER | docerr
  2704.  Last Modified: 24-AUG-1988    ArticleIdent: Q31454
  2705.  
  2706.     The following statement appears in the note for Page 130 ("Part 2:
  2707.  Notes for the Microsoft C Optimizing Compiler User's Guide") of the
  2708.  README.DOC file on the C Version 5.10 Setup disk:
  2709.  
  2710.     See the description of the /NOE option under the heading "Linker
  2711.  Options" later in this document.
  2712.  
  2713.     However, there is no such heading, nor is there any linker option
  2714.  information in the UTILITY.DOC file.
  2715.     The CodeView and Utilities manual contains an inserted manual
  2716.  section labelled "Update (CV. and Util.)". In this document, the /NOE
  2717.  option and the /NON option are described in Section 4, "Using the OS/2
  2718.  Linker", subsection 4.3, "New Options for Both Modes", Page Update-28.
  2719.  
  2720.  
  2721.  51. PATCH87 Gives "Cannot Open IO.SYS" Message
  2722.  
  2723.  Product Version(s): 5.10
  2724.  Operating System:   MS-DOS
  2725.  Flags: ENDUSER |
  2726.  Last Modified: 16-JUN-1988    ArticleIdent: Q31468
  2727.  
  2728.     If the instructions in the PATCH87.DOC file for using PATCH87.EXE
  2729.  are followed through Step 4 of the "Do I Need to Use This Program?"
  2730.  section, and the diagnostic test results in a "Cannot open IO.SYS"
  2731.  message, then you must contact the original equipment manufacturer
  2732.  (OEM) for more information. It is likely that the IO.SYS file has been
  2733.  renamed in the provided version of DOS.
  2734.  
  2735.  
  2736.  52. Bitwise Complement Operator Appears to Fail on Comparison
  2737.  
  2738.  Product Version(s): 4.00 5.10 5.00
  2739.  Operating System:   MS-DOS
  2740.  Flags: ENDUSER |
  2741.  Last Modified: 16-JUN-1988    ArticleIdent: Q31510
  2742.  
  2743.     The bitwise complement operator (~) may appear to work incorrectly
  2744.  when used to compare unsigned characters, as illustrated in the
  2745.  following example.
  2746.     However, when using the bitwise complement operator, it is
  2747.  important to note that it will perform the "usual arithmetic
  2748.  conversions" on operands. The usual arithmetic conversions are
  2749.  described in detail in Section 5.3.1 of "The Microsoft C Language
  2750.  Reference Guide."
  2751.  
  2752.     The following program prints out as "failed" even though it
  2753.  appears that the two items should compare as "equal":
  2754.  
  2755.  #include <stdio.h>
  2756.  main()
  2757.  {
  2758.   unsigned char i,j;
  2759.   unsigned char k = 4;
  2760.   i = k;
  2761.   j = ~i;
  2762.  
  2763.    if (j == ~i)
  2764.      printf("passed\n");
  2765.    else
  2766.      printf("failed\n");
  2767.  
  2768.  }
  2769.  
  2770.     The compiler takes the steps below to evaluate the following
  2771.  statement:
  2772.  
  2773.     if (j == ~i)
  2774.  
  2775.     1. The compiler converts the operand "i" to an unsigned integer (in
  2776.  the C manual, see step 5 of the usual arithmetic conversions).
  2777.     2. The compiler complements the bits of this unsigned integer (the
  2778.  high byte becomes 0xFF).
  2779.     3. The compiler converts the operand "j" to an unsigned integer
  2780.  (the high byte becomes 0x00).
  2781.     4. The compiler compares the two operands.
  2782.  
  2783.     Since the high bytes of the two operands differ, the comparison
  2784.  will fail.
  2785.     To ensure that the compiler will compare only the low bytes of the
  2786.  two operands, cast the operand that is being complemented. For
  2787.  example, you can change the comparison to the following:
  2788.  
  2789.   if (j == ~(unsigned char)i)
  2790.  
  2791.  
  2792.  53. Linking FORTRAN and C, "L2044 _FF_MsgBanner Multiply Defined"
  2793.  
  2794.  Product Version(s): 5.00 5.10
  2795.  Operating System:   MS-DOS
  2796.  Flags: ENDUSER | h_fortran 4.00 4.01
  2797.  Last Modified: 16-JUN-1988    ArticleIdent: Q31563
  2798.  
  2799.  Problem:
  2800.     When linking FORTRAN and C modules, I receive the error "L2044
  2801.  _FF_MsgBanner Symbol Multiply Defined." I have set up FORTRAN for C
  2802.  compatibility, and I am linking with the /NOE switch.
  2803.  
  2804.  Response:
  2805.     When using FORTRAN Versions 4.00 or 4.01 with C, you need to run
  2806.  the F4COMPAT file to make your FORTRAN libraries C compatible because
  2807.  FORTRAN Versions 4.00 and 4.01 were written in C Version 4.00.
  2808.     If the /NOD switch is used, altering the order of the libraries may
  2809.  change the error message received. When the FORTRAN library is first,
  2810.  the error may be "Floating Point Not Loaded." When the C library is
  2811.  first, the error will be "Symbol Multiply Defined."
  2812.  
  2813.  
  2814.  54. RunTmLibRef ftime Returns millitm to 100ths
  2815.  
  2816.  Product Version(s): 4.00 5.00 5.10 | 5.10
  2817.  Operating System:   MS-DOS         | OS/2
  2818.  Flags: ENDUSER | docerr
  2819.  Last Modified: 12-OCT-1988    ArticleIdent: Q31611
  2820.  
  2821.     The ftime function is described in a misleading way in the
  2822.  "Microsoft C 5.1 Optimizing Compiler Run-Time Library Reference" ,
  2823.  Page 308 for C Version 5.x and Page 217 for C Version 4.00.
  2824.     The field millitm in the timeb structure that ftime returns is
  2825.  described to hold the value of the fraction of a second in
  2826.  milliseconds. The field contains three digits as described;
  2827.  however, the last digit always is zero. Thus, the function returns
  2828.  millitm incremented to the nearest one hundredth of a second.
  2829.     Note also that this function uses the system clock to determine
  2830.  the time. Since the resolution of the clock on PC's is about 1/18.2
  2831.  seconds, the time function can not be more accurate than that.
  2832.  
  2833.  
  2834.  55. _beginthread()/_endthread() Coding Multi-Threaded Applications
  2835.  
  2836.  Product Version(s): 5.10
  2837.  Operating System:   OS/2
  2838.  Flags: ENDUSER |
  2839.  Last Modified:  8-JUL-1988    ArticleIdent: Q32057
  2840.  
  2841.  Question:
  2842.     What do _beginthread() and _endthread() do? Do we need to use
  2843.  these routines rather than the OS/2 API calls DosCreateThread() and
  2844.  DosExit()? Does _beginthread() affect the stack it is passed?
  2845.  
  2846.  Response:
  2847.     _beginthread() and _endthread() are discussed in MTDYNA.DOC.
  2848.     _beginthread() should be used in place of DosCreateThread() when
  2849.  coding multi-threaded applications in C Version 5.10. _endthread()
  2850.  should be used rather than DosExit() to terminate a thread before it
  2851.  runs to completion.
  2852.     _beginthread() takes care of important thread-creation tasks,
  2853.  such as the following:
  2854.  
  2855.     1. Initializing the per-thread floating-point package
  2856.     2. Saving/restoring the DGROUP environment
  2857.     3. Ensuring that there are not too many threads being created
  2858.     4. Verifying the validity of the stack generated
  2859.  
  2860.     The stack you pass to _beginthread() must meet the following
  2861.  requirements:
  2862.  
  2863.     1. It must not have null segment.
  2864.     2. It must not start at an odd address.
  2865.     3. It must not have 0 length.
  2866.     4. It must not have an odd length.
  2867.     5. It must not extend past the end of the segment.
  2868.  
  2869.     Because of the importance of these tasks, it is important to use
  2870.  _beginthread()/_endthread() instead of DosCreateThread()/ DosExit()
  2871.  when coding multi-threaded applications in C Version 5.10. Although
  2872.  you may be able to use DosCreateThread(), consistent results are not
  2873.  guaranteed.
  2874.  
  2875.  
  2876.  56. Compiler C2061 Syntax Error: Identifier 'dev_t' in stat.h
  2877.  
  2878.  Product Version(s): 5.10   | 5.10
  2879.  Operating System:   MS-DOS | OS/2
  2880.  Flags: ENDUSER |  s_quickc
  2881.  Last Modified: 15-JAN-1990    ArticleIdent: Q32068
  2882.  
  2883.  When compiling a file that includes stat.h or stat.h followed by an
  2884.  include of types.h, the following error is generated:
  2885.  
  2886.     C2061 syntax error: identifier 'dev_t'
  2887.  
  2888.  The error occurs because dev_t is defined in types.h and is not
  2889.  defined in stat.h.
  2890.  
  2891.  When using the include file stat.h, you must also include the file
  2892.  types.h. Specifically, the file types.h must be included before the
  2893.  file stat.h. For example:
  2894.  
  2895.  #include <sys\types.h>
  2896.  #include <sys\stat.h>
  2897.  
  2898.  The order in which these files are included must occur as shown to
  2899.  eliminate the compiler error message.
  2900.  
  2901.  
  2902.  57. No Error Message Text
  2903.  
  2904.  Product Version(s): 5.00 5.10
  2905.  Operating System:   MS-DOS
  2906.  Flags: ENDUSER |
  2907.  Last Modified: 26-SEP-1988    ArticleIdent: Q32069
  2908.  
  2909.  You can receive compiler errors with numbers but without text when
  2910.  compiling if the error message's file is not present.
  2911.  
  2912.  To see the error-message text, the files C1.ERR and C23.ERR must be in
  2913.  your path. Generally, these two files are placed in the same directory
  2914.  as the compiler driver and compiler passes, CL.EXE, C1.EXE, C2.EXE, and
  2915.  C3.EXE.
  2916.  
  2917.  
  2918.  58. D1001 "Could Not Execute C2.EXE" with DOS Version 2.10
  2919.  
  2920.  Product Version(s): 5.10
  2921.  Operating System:   MS-DOS
  2922.  Flags: ENDUSER |
  2923.  Last Modified: 23-SEP-1988    ArticleIdent: Q32070
  2924.  
  2925.  The compiler can generate the error D1001, "could not execute C2.EXE,"
  2926.  under the following conditions:
  2927.  
  2928.  1. The .EXE file cannot be found. A terminate-and-stay-resident
  2929.     (TSR) program could alter the setting of the PATH environment
  2930.     variable, causing the .EXE to not be found.
  2931.  
  2932.  2. There is not enough memory.
  2933.  
  2934.  3. The .EXE file is corrupt, or has an illegal .EXE file format.
  2935.  
  2936.  4. DOS and COMMAND.COM are incompatible. If their version numbers
  2937.     are different, the compiler might not be able to open the
  2938.     intermediate file in the TMP directory.
  2939.  
  2940.  
  2941.  59. Two Syntaxes for Calling Functions with Pointers
  2942.  
  2943.  Product Version(s): 5.10
  2944.  Operating System:   MS-DOS
  2945.  Flags: ENDUSER |
  2946.  Last Modified: 26-SEP-1988    ArticleIdent: Q32109
  2947.  
  2948.  The source code below contains what appears to be an improper use of a
  2949.  pointer to a function. However, the compiler fails to flag this either
  2950.  as a warning or as an error, and the code seems to work as expected.
  2951.  
  2952.  The behavior exhibited in the sample code is expected. The proposed
  2953.  ANSI Standard (Document Number X3J11/88-002, January 11, 1988) allows
  2954.  a function to be called through a pointer with the following syntax
  2955.  
  2956.  pointer_to_function();
  2957.  
  2958.  in addition to the following traditional syntax:
  2959.  
  2960.  (*pointer_to_function)();
  2961.  
  2962.  The following is a quotation from Page 40 of "Rationale for Draft
  2963.  Proposed American National Standard for Information Systems
  2964.  Programming Language C":
  2965.  
  2966.  "The...construct, not sanctioned in the Base Document, appears in some
  2967.  present versions of C, is unambiguous, invalidates no old code, and
  2968.  can be an important shorthand."
  2969.  
  2970.  The following sample code demonstrates this problem:
  2971.  
  2972.  #include <stdio.h>
  2973.  void main()
  2974.  {
  2975.     void ftn();
  2976.     void (*ptr_to_ftn)();
  2977.     ptr_to_ftn = ftn; /* the pointer is correctly assigned to
  2978.                          an address */
  2979.     printf("\nCalling all ftns\n\n");
  2980.     (ptr_to_ftn)();  /* note that the function is improperly called.
  2981.                         the correct syntax is (*ptr_to_ftn)() */
  2982.     printf("back to main\n");
  2983.  }
  2984.  void ftn()
  2985.  {
  2986.     printf("inside ftnland\n\n");
  2987.  }
  2988.  
  2989.  
  2990.  60. EXEC Problem with the Novell Network
  2991.  
  2992.  Product Version(s): 4.00 5.00 5.10
  2993.  Operating System:   MS-DOS
  2994.  Flags: ENDUSER |
  2995.  Last Modified: 12-OCT-1988    ArticleIdent: Q32285
  2996.  
  2997.  When compiling a program under a Novell network, the following
  2998.  problems can occur:
  2999.  
  3000.  1. A command-line error message.
  3001.  2. A stack overflow.
  3002.  3. The compiler hangs.
  3003.  4. Programs created with C Version 4.00 and Link Version 3.51
  3004.     could generate Error 2003 : integer divide by zero.
  3005.  
  3006.  This is not a problem with the Microsoft C Compiler, nor is it an
  3007.  error on your part. A problem exists in the way Novell networking
  3008.  software handles the EXEC function, one of the DOS interrupt 21h
  3009.  functions used by the CL and MSC programs to start each of the
  3010.  compiler passes.
  3011.  
  3012.  Contact your Novell dealer about this problem; there should be a patch
  3013.  available. Novell has stated this problem has been corrected in
  3014.  Version 2.10 and later.
  3015.  
  3016.  Novell's network emulates DOS; the problem arises from incorrect
  3017.  emulation of the DOS int 21H function 4BH (EXEC program) call. The
  3018.  Novell network assumes the calling program will save SS:SP before the
  3019.  call. This was necessary on DOS Versions 2.x, but it is not necessary
  3020.  to save the registers on DOS Versions 3.x.
  3021.  
  3022.  The C compiler checks to see what version of DOS it is running on; if
  3023.  you are running DOS Versions 2.x, save SS:SP; if you are running DOS
  3024.  Versions 3.x (which is what Novell presents itself as) do not save
  3025.  SS:SP. The network destroys those registers on the call even though
  3026.  this behavior is unlike DOS Versions 3.x.
  3027.  
  3028.  
  3029.  61. Assert Macro Anomaly; Generating Syntax Errors
  3030.  
  3031.  Product Version(s): 5.10   | 5.10
  3032.  Operating System:   MS-DOS | OS/2
  3033.  Flags: ENDUSER |
  3034.  Last Modified:  5-JUL-1988    ArticleIdent: Q32303
  3035.  
  3036.     The following code demonstrates an anomaly with the C Version 5.10
  3037.  compiler when compiled with the default options. Compile-time syntax
  3038.  warnings are generated when there are no apparent syntax errors.
  3039.  
  3040.  #include <stdio.h>
  3041.  #include <assert.h>
  3042.  main()
  3043.  {
  3044.    if(1)
  3045.    assert(1+1);
  3046.    else
  3047.    assert(1+2);
  3048.  }
  3049.  
  3050.  Response:
  3051.     The syntax errors are generated because assert() is implemented as
  3052.  a macro and is expanded to the following form:
  3053.  
  3054.      if (!(1+1)) { \
  3055.          fprintf(stderr, _assertstring, #1+1, __FILE__, __LINE__); \
  3056.          fflush(stderr); \
  3057.          abort(); \
  3058.          } \
  3059.      }
  3060.  
  3061.     When this macro is placed inside an if else conditional, the
  3062.  closing brace of the macro is seen as a syntax error.
  3063.     Although the syntax for the if else conditional in the above
  3064.  example is legal, it does not make much sense for use with assert
  3065.  because assert will call the abort function if it is true. Therefore,
  3066.  you can accomplish the same results with the following program:
  3067.  
  3068.  #include <stdio.h>
  3069.  #include <assert.h>
  3070.  main()
  3071.  {
  3072.    if(1)
  3073.    assert(1+1);
  3074.    assert(1+2);
  3075.  }
  3076.  
  3077.     Microsoft is researching this problem and will post new information
  3078.  as it becomes available.
  3079.  
  3080.  
  3081.  62. L1063 Error Not Documented in C Versions 5.00 or 5.10
  3082.  
  3083.  Product Version(s): 5.00 5.10 | 5.10
  3084.  Operating System:   MS-DOS    | OS/2
  3085.  Flags: ENDUSER | docerr
  3086.  Last Modified: 18-AUG-1988    ArticleIdent: Q32311
  3087.  
  3088.     The link error message, "L1063 out of memory for CodeView
  3089.  information," is not documented in the manuals or in the README.DOCs
  3090.  for C Versions 5.00 and 5.10. However, it is documented in the FORTRAN
  3091.  Version 4.10 package in the CVREADME.DOC on the disk labeled
  3092.  "Microsoft CodeView for MS-DOS".
  3093.     The following information was taken from the FORTRAN Version 4.10
  3094.  CVREADME.DOC, "NOTES ON CODEVIEW AND UTILITIES," the section titled
  3095.  "Microsoft Segmented-Executable Linker (LINK)," the subsection "New
  3096.  LINK Error Messages":
  3097.  
  3098.     L1063 out of memory for CodeView information
  3099.  
  3100.     The linker was given too many object files with debug information,
  3101.  and the linker ran out of space to store it. Reduce the number of
  3102.  object files that have debug information.
  3103.  
  3104.  
  3105.  63. C 5.00 and 5.10 putenv() Example Program Missing Backslashes
  3106.  
  3107.  Product Version(s): 5.00 5.10 | 5.10
  3108.  Operating System:   MS-DOS    | OS/2
  3109.  Flags: ENDUSER | docerr
  3110.  Last Modified: 15-JAN-1991    ArticleIdent: Q32324
  3111.  
  3112.  The example program for the putenv() function on page 468 of the
  3113.  "Microsoft C 5.10 Optimizing Compiler Run-Time Library Reference" is
  3114.  incorrect. The C code requires double backslashes in order to work
  3115.  correctly.
  3116.  
  3117.  This is the incorrect line:
  3118.  
  3119.     if (putenv("PATH=a\bin;b:\tmp") == 1)
  3120.  
  3121.  The corrected line (with escaped backslashes) should read as follows:
  3122.  
  3123.     if (putenv("PATH=a:\\bin;b:\\tmp") == 1)
  3124.  
  3125.  
  3126.  64. Incorrect Comment Pragma Example
  3127.  
  3128.  Product Version(s): 5.10   | 5.10
  3129.  Operating System:   MS-DOS | OS/2
  3130.  Flags: ENDUSER | docerr
  3131.  Last Modified: 15-JAN-1990    ArticleIdent: Q32348
  3132.  
  3133.  Page 12 (Update-12) of the Update section for the "Microsoft C
  3134.  Optimizing Compiler User's Guide and Language Reference" manual shows
  3135.  an incorrect example of the comment pragma.
  3136.  
  3137.  The second parameter of the pragma is a string literal and should be
  3138.  enclosed in double quotation marks. The example should look like the
  3139.  following:
  3140.  
  3141.     #pragma comment(lib, "mylibry")
  3142.  
  3143.  Note: If the quotation marks are missing, the compiler will issue
  3144.  error C4079.
  3145.  
  3146.  
  3147.  65. _Heapchk() Performs Consistency Check on Heap
  3148.  
  3149.  Product Version(s): 5.10   | 5.10
  3150.  Operating System:   MS-DOS | OS/2
  3151.  Flags: ENDUSER |
  3152.  Last Modified: 12-JUL-1988    ArticleIdent: Q32442
  3153.  
  3154.     The _heapchk() routine performs a consistency check on the heap by
  3155.  examining the header information of the memory blocks in the heap.
  3156.  However, it cannot detect corruption of data within the heap's nodes;
  3157.  it only can detect corruption of the heap's header information.
  3158.     The _heapchk() routine checks for the following:
  3159.  
  3160.     1. It checks to see if any heap has been allocated at all. If not,
  3161.        _heapchk() returns _HEAPEMPTY.
  3162.     2. It checks the beginning of the heap block to see if the first
  3163.        allocation block has been corrupted; if so, it returns _HEAPBADBEGIN.
  3164.        (Note that only the header information is checked.)
  3165.     3. It scans through the far heap block, moving from node to node.
  3166.        For each node, it checks the header information to make sure it has
  3167.        not been corrupted; if so, _heapchk() returns _HEAPBADNODE.
  3168.        Note that the only kind of corruption _heapchk() can detect is an
  3169.        out-of-bounds value in the header; it cannot detect corrupted data
  3170.        within the heap block itself. If the fill value passed is not
  3171.        _HEAPSET_NOFILL, and the block is unallocated, _heapchk() fills
  3172.        memory with the fill value.
  3173.     4. If _heapchk() made it all the way through the heap (i.e., it checked
  3174.        the headers for all nodes), it returns _HEAPOK.
  3175.  
  3176.  
  3177.  
  3178.  66. How Bitfields Are Stored in Memory
  3179.  
  3180.  Product Version(s): 1.04 2.03 3.00 4.00 5.00 5.10 | 5.10
  3181.  Operating System:   MS-DOS                        | OS/2
  3182.  Flags: ENDUSER |
  3183.  Last Modified: 19-JUL-1988    ArticleIdent: Q32841
  3184.  
  3185.     The Microsoft C compiler stores bitfields from low memory to high
  3186.  memory. For example, if you have the following declaration:
  3187.  
  3188.             struct   {
  3189.                     unsigned field_one:3;
  3190.                     unsigned field_two:9;
  3191.                     unsigned field_three:5;
  3192.             };
  3193.  
  3194.  then "field_one" will be stored in bits 0-2 in the first word,
  3195.  "field_two" will be stored in bits 3-11 in the same word, and
  3196.  "field_three" will be stored in bits 0-4 of the second word (because
  3197.  it cannot fit in the 4 bits remaining in the current word).
  3198.  
  3199.  
  3200.  
  3201.  67. Specifying .DEF Files on the CL Command Line
  3202.  
  3203.  Product Version(s): 5.10   | 5.10
  3204.  Operating System:   MS-DOS | OS/2
  3205.  Flags: ENDUSER |
  3206.  Last Modified:  8-JUL-1988    ArticleIdent: Q32448
  3207.  
  3208.     You can use .DEF files when compiling and linking, using CL
  3209.  command-lines.
  3210.     List the .DEF files with the other files (.C, .OBJ, and .LIB). CL
  3211.  will compile and link them appropriately. Note that if you do not
  3212.  specify an extension, CL assumes the file is an .OBJ file and it will
  3213.  try to link it.
  3214.     The following command will build a protected-mode program called
  3215.  MYAPP.EXE by compiling myapp.c, then linking MYAPP.OBJ and MYSUB.OBJ
  3216.  with the library MYLIB.LIB, and use the MYDEF.DEF.definitions file:
  3217.  
  3218.      cl /Lp myapp.c mysub mylib.lib mydef.def
  3219.  
  3220.  
  3221.  
  3222.  68. ANSI Constants Not in Stdio.h
  3223.  
  3224.  Product Version(s): 5.10   | 5.10
  3225.  Operating System:   MS-DOS | OS/2
  3226.  Flags: ENDUSER |
  3227.  Last Modified:  8-JUL-1988    ArticleIdent: Q32513
  3228.  
  3229.     The ANSI C standard requires the constants FILENAME_MAX and
  3230.  FOPEN_MAX in STDIO.H and the constants EXIT_SUCCESS and EXIT_FAILURE
  3231.  in STDLIB.H.
  3232.     The include files provided with Version 5.10 of the C compiler do not
  3233.  have these constants. These constants should be defined as follows:
  3234.  
  3235.  /* in stdio.h */
  3236.  
  3237.  #define FILENAME_MAX 63
  3238.  #define FOPEN_MAX    20
  3239.  
  3240.  /* in stdlib.h */
  3241.  
  3242.  #define EXIT_SUCCESS  0
  3243.  #define EXIT_FAILURE  1
  3244.  
  3245.  
  3246.  
  3247.  69. fclose() on Unopened Files Causes Protection Violation
  3248.  
  3249.  Product Version(s): 5.10   | 5.10
  3250.  Operating System:   MS-DOS | OS/2
  3251.  Flags: ENDUSER |
  3252.  Last Modified: 11-AUG-1988    ArticleIdent: Q32539
  3253.  
  3254.     If you close an unopened file with the fclose() function, a
  3255.  protection violation occurs if the source is compiled in the large- or
  3256.  compact-memory model. In the small-memory model, fclose() returns an
  3257.  error as expected.
  3258.     Closing an unopened file is a user error and it is outside the
  3259.  functional realm of the C run time to check the validity of file
  3260.  handles passed to the fclose function. It is the responsibility of the
  3261.  user to ensure that only valid file handles are passed to the fclose
  3262.  function.
  3263.  
  3264.     The sample code below demonstrates this behavior. Compile this code
  3265.  with the CL /AL file.c. command line:
  3266.  
  3267.  #define INCL_BASE
  3268.  #include <os2.h>
  3269.  #include <stdio.h>
  3270.  FILE *myfile;
  3271.  int status;
  3272.  
  3273.  main()
  3274.  {
  3275.   myfile = fopen("myfile.dat","r");
  3276.   if (myfile == NULL) printf("file open error\n");
  3277.   status = fclose(myfile);
  3278.   printf("file close status = %d\n",status);
  3279.  }
  3280.  
  3281.  
  3282.  70. Reference to Section 2.11 Should Be 2.12 in User's Guide
  3283.  
  3284.  Product Version(s): 5.10   | 5.10
  3285.  Operating System:   MS-DOS | OS/2
  3286.  Flags: ENDUSER | docerr
  3287.  Last Modified: 18-AUG-1988    ArticleIdent: Q32805
  3288.  
  3289.     Page 145 of the "Microsoft C 5.0 (and 5.1) Optimizing Compiler User's
  3290.  Guide" has an error in the last sentence. The reference to Section
  3291.  2.11 is incorrect; it should read as follows:
  3292.  
  3293.     "For more information on library routines and memory models, see
  3294.  Section 2.12, `Using Huge Arrays with Library Functions,' in the
  3295.  Microsoft C Run-Time Library Reference."
  3296.  
  3297.  
  3298.  
  3299.  71. The fopen Function Fails to Open Printer in Bound Application
  3300.  
  3301.  Product Version(s): 5.10   | 5.10
  3302.  Operating System:   MS-DOS | OS/2
  3303.  Flags: ENDUSER |
  3304.  Last Modified: 12-JAN-1990    ArticleIdent: Q32813
  3305.  
  3306.  Attempting to use the C run-time function fopen() to open the printer
  3307.  will fail in real mode if the application calling the function is
  3308.  bound. The "invalid argument" error is returned.
  3309.  
  3310.  This problem is caused by the Family API DosOpen function. It will
  3311.  fail to open the printer when called with a flag that specifies
  3312.  "truncate if the file exists," which is the flag used by fopen().
  3313.  
  3314.  The following program demonstrates a work around for this problem
  3315.  using the C run-time library functions open() and fdopen():
  3316.  The program below uses open() to get a file handle for the printer.
  3317.  Note that the oflag used is O_WRONLY. ORing in O_TRUNC would fail in
  3318.  real mode. The device name "lpt1" or "lpt2" could be used instead of
  3319.  "prn", depending on how the computer is set up. The generic name for
  3320.  the printer is "prn".
  3321.  
  3322.  Then the fdopen() function is used to create a stream for the printer,
  3323.  and the printer is written to by the fprintf() function.
  3324.  
  3325.  The following is the sample program:
  3326.  
  3327.  #include <fcntl.h>      /* include files for open() */
  3328.  #include <sys\types.h>
  3329.  #include <sys\stat.h>
  3330.  #include <io.h>
  3331.  #include <stdio.h>      /* include file for printf() and
  3332.  fdopen() */
  3333.  
  3334.  int   fh;     /* file handle for printer */
  3335.  FILE *stream; /* stream for printer     */
  3336.  
  3337.  main() {
  3338.  /* open file handle for printer, check for open failure */
  3339.      if ((fh = open("prn",O_WRONLY)) == -1 )
  3340.          printf("Opening file handle failed.\n");
  3341.  
  3342.  /* associate stream for fh above, check for failure */
  3343.      else {
  3344.          if((stream = fdopen(fh,"w")) == NULL)
  3345.              printf("Creation of stream from file handle
  3346.  failed.\n");
  3347.  
  3348.  /* if previous function calls succeeded, print "Hello" */
  3349.          else
  3350.              fprintf(stream,"Hello\n");
  3351.          }
  3352.      }
  3353.  
  3354.  
  3355.  72. The Cause of Run-Time Error R6000 Stack Overflow
  3356.  
  3357.  Product Version(s): 4.00 5.00 5.10 | 5.10
  3358.  Operating System:   MS-DOS         | OS/2
  3359.  Flags: ENDUSER |
  3360.  Last Modified: 12-OCT-1988    ArticleIdent: Q32816
  3361.  
  3362.  The run-time error R6000 Stack Overflow can be caused by two
  3363.  different problems, as follows:
  3364.  
  3365.  1. Your program's stack is not large enough to hold all the data
  3366.     being pushed on it during execution of your program, so it
  3367.     overflowed. This problem can be caused by heavily recursive
  3368.     programs and programs that declare large amounts of data on
  3369.     the stack ("local" or "automatic" data in C jargon).
  3370.  
  3371.     In this case, you need a larger stack or less recursion and/or less
  3372.     local data.
  3373.  
  3374.  2. The second cause for the R6000 error is somewhat counter
  3375.     intuitive; it can be caused by the C startup (initialization)
  3376.     code when it tries to allocate space for the stack and is unable
  3377.     to do so.
  3378.  
  3379.     In this case, you need to reduce the size of your stack or reduce
  3380.     the amount of data in DGROUP.
  3381.  
  3382.  The following is a description of both problems, ways to solve the
  3383.  problem, and a method for determining which problem you are
  3384.  encountering:
  3385.  
  3386.  Case 1: R6000 Occurs at Run Time
  3387.  
  3388.  The stack overflowed because too much information was pushed on it.
  3389.  This information could be either function-return addresses or local
  3390.  data. Each time a function is called, the return address in the
  3391.  calling function is pushed on the stack along with any parameters;
  3392.  then, when the called function executes, it may allocate local
  3393.  ("automatic") data for its own use. This process requires stack space.
  3394.  
  3395.  To correct this problem, do one of the following:
  3396.  
  3397.  1. Decrease the number of local variables, perhaps by declaring
  3398.     those variables as static so they will not be pushed on the
  3399.     stack.
  3400.  
  3401.  2. Increase the stack size by compiling with the /F x option, where
  3402.     x is a hexadecimal number representing the number of bytes
  3403.     desired in the stack size (see Page 102 of the "Microsoft C 5.1
  3404.     Optimizing Compiler User's Guide").
  3405.  
  3406.  3. Change the stack size by linking with the /STACK switch, or using
  3407.     the EXEMOD utility. Note that increasing the stack size too much
  3408.     can cause an R6000 as described in case 2.
  3409.  
  3410.  Case 2: R6000 Occurs at Startup
  3411.  
  3412.  The startup code allocates space for the stack in the segment DGROUP.
  3413.  If DGROUP does not contain room for the specified stack size (default
  3414.  = 2K), the startup code issues the R6000 error.
  3415.  
  3416.  To correct this problem, either reduce the size of the stack or reduce
  3417.  the amount of data in DGROUP. To reduce the stack size, compile with
  3418.  the /F option, or link with the /STACK option, or use the EXEMOD
  3419.  utility. To reduce the amount of data in DGROUP, try switching from a
  3420.  small-data model (Small- or Medium-memory model) to a large-data model
  3421.  (Compact-, Large-, or Huge-memory model). If you already are in a
  3422.  large-data model, compile with the /Gt switch to move data from DGROUP
  3423.  to far data segments.
  3424.  
  3425.  To use the /Gt switch, specify /Gtx, where x is some decimal value
  3426.  representing a number of bytes. Data items larger than x bytes are
  3427.  allocated a new segment, thereby freeing up more space in DGROUP for
  3428.  the stack. For more information, see Page 156 of the "Microsoft C 5.1
  3429.  Optimizing Compiler User's Guide."
  3430.  
  3431.  How to Determine What is Causing the R6000 Error
  3432.  
  3433.  An excellent way to determine the cause of the problem is to use the
  3434.  CodeView debugger. After invoking CodeView on your program, execute to
  3435.  the beginning of function main() by doing one of the following:
  3436.  
  3437.  1. Single-Step with F8 or T.
  3438.  2. Enter "g main" at the CodeView prompt.
  3439.  
  3440.  When you've executed past the open curly-brace of main(), the C
  3441.  startup code has done its job by allocating space for stack and data.
  3442.  If the R6000 error does not occur at this time, you are experiencing
  3443.  Case 1, a run-time stack overflow (as opposed to Case 2, a
  3444.  startup-time stack overflow); you now can take appropriate action as
  3445.  described above.
  3446.  
  3447.  
  3448.  73. Command Line Error D2018
  3449.  
  3450.  Product Version(s): 5.00 5.10 | 5.10
  3451.  Operating System:   MS-DOS    | OS/2
  3452.  Flags: ENDUSER |
  3453.  Last Modified: 19-JUL-1988    ArticleIdent: Q32843
  3454.  
  3455.     If you receive the D2018: "cannot open linker cmd file" error,
  3456.  check to see that the TMP environment variable is set correctly. If
  3457.  the TMP variable is not set properly, temporary files cannot be
  3458.  created and this error may occur.
  3459.  
  3460.  
  3461.  
  3462.  74. Write Function Will Not Work Correctly with SS!=DS
  3463.  
  3464.  Product Version(s): 5.00 5.10 | 5.10
  3465.  Operating System:   MS-DOS    | OS/2
  3466.  Flags: ENDUSER |
  3467.  Last Modified: 19-JUL-1988    ArticleIdent: Q32871
  3468.  
  3469.  Problem:
  3470.     I have a program that needs to be run in an SS!=DS environment and
  3471.  I am trying to use the write function; however, it does not seem to be
  3472.  working.
  3473.  
  3474.  Response:
  3475.     The write function will not work correctly in SS!= DS in text
  3476.  mode. It should work properly in binary mode. In text mode, write()
  3477.  builds a buffer on the stack to do LF to CR/LF translation. It makes a
  3478.  call to stackavail() to make sure it does not overflow the stack; this
  3479.  call is what prevents it from working with SS!=DS.
  3480.     This is program design for this product.
  3481.  
  3482.  
  3483.  75. Toggling the Sign Bit on a Float or Double
  3484.  
  3485.  Product Version(s): 3.00 4.00 5.00 5.10
  3486.  Operating System:   MS-DOS
  3487.  Flags: ENDUSER |
  3488.  Last Modified: 20-JUL-1988    ArticleIdent: Q32889
  3489.  
  3490.  Problem:
  3491.     I want to toggle the sign bit on a float or double by either
  3492.  and'ing it with 0x7fff (make it positive) or or'ing it with 0x8000
  3493.  (make it negative). However, the compiler will not accept the
  3494.  following syntax:
  3495.  
  3496.     fl &= 0x7fff;
  3497.     fl |= 0x8000;
  3498.  
  3499.  Response:
  3500.     The bitwise operators only works correctly with integral types; you
  3501.  need to cast the float to be an integral type.
  3502.     The following are two macros that will allow you to toggle the sign
  3503.  bit on a float or a double (note that the same thing can be
  3504.  accomplished by multiplying the value by -1, but the macros are much
  3505.  faster because they do not make any calls to the floating-point
  3506.  library):
  3507.  
  3508.  /* Macro to make either a float or a double Negative by setting sign bit */
  3509.  #define NEG(arg) ((unsigned char *)&arg)[sizeof(arg)-1] |= \
  3510.                     (unsigned char)0x8000
  3511.  
  3512.  /* Macro to make either a float or a double Positive by clearing sign bit */
  3513.  #define POS(arg) ((unsigned char *)&arg)[sizeof(arg)-1] &= \
  3514.                     (unsigned char)0x7fff
  3515.  
  3516.  
  3517.  
  3518.  76. extern int i = 10; Compiles without Error
  3519.  
  3520.  Product Version(s): 5.10   | 5.10
  3521.  Operating System:   MS-DOS | OS/2
  3522.  Flags: ENDUSER | docerr
  3523.  Last Modified: 19-JUL-1988    ArticleIdent: Q32890
  3524.  
  3525.     Page 89 of "Microsoft C Optimizing Compiler Language Reference"
  3526.  states the following:
  3527.  
  3528.    "Declarations that use the extern storage-class specifier cannot
  3529.  include initializers."
  3530.  
  3531.    However, the following example compiles without error:
  3532.  
  3533.    extern int i = 10;
  3534.  
  3535.    The documentation is incorrect. The ANSI standard makes no
  3536.  distinction between the following declarations when they have file
  3537.  scope (i.e., they are declared globally):
  3538.  
  3539.    int i = 10;
  3540.    extern int i = 10;
  3541.  
  3542.    Therefore, the compiler does not generate a warning or error for
  3543.  either of these cases.
  3544.  
  3545.  
  3546.  
  3547.  77. __fac Unresolved at Link Time
  3548.  
  3549.  Product Version(s): 5.10   | 5.10
  3550.  Operating System:   MS-DOS | OS/2
  3551.  Flags: ENDUSER |
  3552.  Last Modified: 19-JUL-1988    ArticleIdent: Q32891
  3553.  
  3554.  Problem:
  3555.     I am attempting to write a function to be used in a dynamic link
  3556.  library. The function returns a double. Whenever I compile and link
  3557.  with either of the multithread C run-time libraries (LLIBCMT.LIB
  3558.  or CRTLIB.LIB), I get the variable __fac unresolved.
  3559.  
  3560.  Response:
  3561.     In a single thread environment, the C run-time uses a global variable
  3562.  __fac to store the return value of a function that returns double. In
  3563.  a multithread reentrant environment, it is not possible to have a global
  3564.  variable that will potentially be modified by several threads.
  3565.     If you are writing functions that return doubles and you are using
  3566.  the multithread libraries, you need to declare the functions with the
  3567.  Pascal calling convention. Functions returning double with the Pascal
  3568.  calling convention pass the return value on the stack and allow you to
  3569.  work in a reentrant environment.
  3570.  
  3571.  
  3572.  
  3573.  78. Compiling with /Zi Causes Code Motion Optimization Suppression
  3574.  
  3575.  Product Version(s): 4.00 5.00 5.10 | 5.10
  3576.  Operating System:   MS-DOS         | OS/2
  3577.  Flags: ENDUSER |
  3578.  Last Modified: 19-JUL-1988    ArticleIdent: Q32892
  3579.  
  3580.     Compiling with /Zi and no other switches causes certain code motion
  3581.  optimizations to be suppressed, i.e, the code generated for a program
  3582.  with the defaults and with /Zi may differ.
  3583.     You can override this default behavior by explicitly specifying the
  3584.  default optimizations on the command line. For example, you can
  3585.  compile with the following command line to get the same code with or
  3586.  without /Zi:
  3587.  
  3588.     cl /Zi /Ot file.c
  3589.  
  3590.  
  3591.  
  3592.  79. Difference between Huge Pointers
  3593.  
  3594.  Product Version(s): 4.00 5.00 5.10 | 5.10
  3595.  Operating System:   MS-DOS         | OS/2
  3596.  Flags: ENDUSER |
  3597.  Last Modified: 19-JUL-1988    ArticleIdent: Q32893
  3598.  
  3599.  Problem:
  3600.     I have two huge pointers that are more than 32K apart. However,
  3601.  whenever I take the difference between them, I get an incorrect
  3602.  answer. I am using the following code:
  3603.  
  3604.  char huge *ptr1 = (char huge *)0xa0000000;
  3605.  char huge *ptr2 = (char huge *)0xb0000000;
  3606.  main()
  3607.  {
  3608.    long k;
  3609.    k = ptr2-ptr1;
  3610.    printf("difference is %ld\n",k);
  3611.  }
  3612.  
  3613.  Response:
  3614.     This problem occurs because the difference between two pointers is
  3615.  considered to be an integer quantity. The arithmetic that is done on
  3616.  the huge pointers is 32-bit arithmetic, but the result is truncated to
  3617.  an integer, then promoted back to a long value with a sign extension.
  3618.     To retain the original long value returned by the huge-pointer
  3619.  arithmetic, cast the result of the subtraction to a long value. For
  3620.  example, you will get the expected results with the following code:
  3621.  
  3622.  char huge *ptr1 = (char huge *)0xa0000000;
  3623.  char huge *ptr2 = (char huge *)0xb0000000;
  3624.  main()
  3625.  {
  3626.    long k;
  3627.    k = (long)(ptr2-ptr1); /* cast the integer to a long */
  3628.    printf("difference is %lp\n",k);
  3629.  }
  3630.  
  3631.  
  3632.  
  3633.  80. malloc May Truncate Request More Than 64K
  3634.  
  3635.  Product Version(s): 4.00 5.00 5.10 | 5.10
  3636.  Operating System:   MS-DOS         | OS/2
  3637.  Flags: ENDUSER |
  3638.  Last Modified: 19-JUL-1988    ArticleIdent: Q32998
  3639.  
  3640.     When trying to allocate memory with malloc() and calloc(), the
  3641.  request for memory will be truncated if it exceeds 64K.
  3642.     The maximum number of bytes that can be allocated by malloc is less
  3643.  than 64K because the allocation routines will consume a certain number
  3644.  of bytes to track memory allocation within the segment. The maximum
  3645.  number of bytes you can allocate using malloc or calloc is
  3646.  approximately 65516.
  3647.     Requests for more than 65516 bytes and less than 64K will result in
  3648.  malloc returning NULL. Requests for more than 64K will potentially
  3649.  return a pointer but it will be a pointer to a block of a size other than
  3650.  that requested because the parameter passed to malloc is an unsigned
  3651.  integer. This integer has a maximum value of 64K; passing a number greater
  3652.  than this value will result in undefined behavior. If malloc is passed a
  3653.  parameter greater than 64K, the compiler will issue a data-conversion
  3654.  warning, which should be heeded.
  3655.     If you require more than about 65516 bytes for a single allocation,
  3656.  you should use halloc().
  3657.  
  3658.     The following program demonstrates the behavior described above:
  3659.  
  3660.  #include <stdio.h>
  3661.  #include <malloc.h>
  3662.  
  3663.  int *intarray;
  3664.  
  3665.  main()
  3666.  {
  3667.      intarray= (int *)malloc(32768*sizeof(int));
  3668.      if (intarray == NULL)
  3669.          printf("not enough memory, no allocation");
  3670.      else
  3671.          printf("memory allocated");
  3672.  
  3673.      intarray= (int *)malloc(32767*sizeof(int));
  3674.      if (intarray == NULL)
  3675.          printf("not enough memory, no allocation");
  3676.      else
  3677.          printf("memory allocated");
  3678.  
  3679.  }
  3680.  
  3681.  
  3682.  
  3683.  81. DOS Append Interacts with /Fo /Fe
  3684.  
  3685.  Product Version(s): 5.10   | 5.10
  3686.  Operating System:   MS-DOS | OS/2
  3687.  Flags: ENDUSER |
  3688.  Last Modified: 20-JUL-1988    ArticleIdent: Q33085
  3689.  
  3690.     When the DOS Append path is set, if an .OBJ or .EXE file of the same
  3691.  name as the file being compiled does not exist in the current
  3692.  directory or in the directory specified with the /Fo or /Fe but does
  3693.  exist in a directory in the Append path, the new .OBJ and .EXE file
  3694.  will be placed in the directory in the Append path instead of in the
  3695.  current directory or the directories specified by the /Fo and /Fe
  3696.  switches.
  3697.     Append searches the data path for all files regardless of
  3698.  extension; placing .OBJ or .EXE in the directory specified in the
  3699.  append directory is expected behavior.
  3700.     If you need to locate files in a specific directory and you are
  3701.  using Append, you should put a copy of the .OBJ and .EXE in the
  3702.  directory you wish to use as your destination.
  3703.  
  3704.     The following is a sample code:
  3705.  
  3706.     append c:\test1,c:\test2
  3707.  
  3708.     If program.obj resides in directory test1 and program.exe
  3709.  resides in test2, the following command line switches will
  3710.  not work correctly:
  3711.  
  3712.  cl /Foc:\test3\program.obj /Fec:\test3\program.exe program.c
  3713.  
  3714.     Although the .OBJ and .EXE files should be placed in the test3
  3715.  directory, they will be placed into the test1 and test2 directories,
  3716.  respectively.
  3717.  
  3718.  
  3719.  
  3720.  82. SH_COMPAT Share Flag for SOPEN()
  3721.  
  3722.  Product Version(s): 5.10   | 5.10
  3723.  Operating System:   MS-DOS | OS/2
  3724.  Flags: ENDUSER | docerr
  3725.  Last Modified:  2-AUG-1988    ArticleIdent: Q33104
  3726.  
  3727.     SH_COMPAT is not a valid share flag for SOPEN() under OS/2.
  3728.  SH_COMPAT is only valid in the DOS environment. The documentation in
  3729.  the "Microsoft C 5.1 Opitimizing Compiler Run-time Library Reference,"
  3730.  Page 548, does not document this restriction on the use of SH_COMPAT.
  3731.  
  3732.  
  3733.  
  3734.  83. Small-Memory Model and Far Routines
  3735.  
  3736.  Product Version(s): 4.00 5.00 5.10 | 5.10
  3737.  Operating System:   MS-DOS         | 5.10
  3738.  Flags: ENDUSER |
  3739.  Last Modified: 27-JUL-1988    ArticleIdent: Q33364
  3740.  
  3741.  Question:
  3742.     Is it incorrect to call a routine with a far call in the small
  3743.  memory model?
  3744.     When I try to call a C routine with a far call (from assembler),
  3745.  the CS register never changes and items start to be executed from the
  3746.  current CS instead of the one my routine is at. Are there any rules
  3747.  that must be followed to make a far call in the small-memory model?
  3748.  
  3749.  Response:
  3750.     In order for this to work correctly you need to be sure that the
  3751.  function is declared and defined as a far function (e.g. int far foo()).
  3752.  
  3753.  
  3754.  
  3755.  84. How _fheapwalk() Checks the Heap
  3756.  
  3757.  Product Version(s): 5.00 5.10 | 5.10
  3758.  Operating System:   MS-DOS    | OS/2
  3759.  Flags: ENDUSER |
  3760.  Last Modified: 27-JUL-1988    ArticleIdent: Q33366
  3761.  
  3762.     The following information describes how _fheapwalk() checks the
  3763.  heap.
  3764.  
  3765.     The _fheapwalk() function traverses those parts of the far heap
  3766.  that have been allocated either by fmalloc() or by a system call. This
  3767.  process is done by covering one such allocation per call of
  3768.  _fheapwalk(), independent of the size of the block allocated.
  3769.     On each call of _fheapwalk(), a manifest-constant int is returned
  3770.  as documented on Page 357 of the "Microsoft C 5.1 Optimizing Compiler
  3771.  Run-Time Reference Library" manual.
  3772.     Also, a pointer to a structure is returned that contains
  3773.  information about the block allocated, which also is documented on
  3774.  Page 356 of the C manual.
  3775.     One undocumented feature of the function is that it does not return
  3776.  the actual memory address of an _fmalloc()ed block, only the block's
  3777.  size.
  3778.     As a result, it is incorrect to assume that the memory location of
  3779.  the beginning of a block can be determined by adding up the values of
  3780.  the blocks already allocated. The header information in each such
  3781.  block is omitted from the structure whose pointer is returned by
  3782.  _fmalloc(). In particular, the size of the header is omitted from the
  3783.  structure.
  3784.  
  3785.  
  3786.  
  3787.  85. Description of the /Or Switch
  3788.  
  3789.  Product Version(s): 5.00 5.10 | 5.10
  3790.  Operating System:   MS-DOS    | OS/2
  3791.  Flags: ENDUSER |
  3792.  Last Modified: 16-JAN-1990    ArticleIdent: Q48089
  3793.  
  3794.  Question:
  3795.  
  3796.  When I run CL with the /HELP option to get command-line help, there is
  3797.  listed an optimization flag, /Or, that is supposed to disable in-line
  3798.  returns. I can't find information about this switch documented
  3799.  anywhere else. What does this switch really do?
  3800.  
  3801.  Response:
  3802.  
  3803.  The term "in-line return" is misleading; there is not a call to the
  3804.  return function that is eliminated. The /Or switch affects the code
  3805.  that is produced for functions lacking local variables and/or formal
  3806.  parameters.
  3807.  
  3808.  If a function takes no formal parameters and has no local variables, a
  3809.  stack frame is not necessary. /Or prevents stack frame creation and
  3810.  clean-up code from being produced when possible. The code for
  3811.  preservation and restoration of the SI and DI registers is also
  3812.  eliminated.
  3813.  
  3814.  The typical instructions that are eliminated are as follows:
  3815.  
  3816.     push bp     ; This code is used on entry
  3817.     mov  bp, sp ; to establish a stack frame.
  3818.     ...
  3819.     push di     ; This code is used on entry
  3820.     push si     ; to preserve SI and DI.
  3821.     ...
  3822.     ...         ; The code to perform the function
  3823.     ...         ; would be here.
  3824.     ...
  3825.     pop  si     ; This code is used on exit to
  3826.     pop  di     ; restore SI and DI, and to
  3827.     mov  sp, bp ; clean up the established
  3828.     pop  bp     ; stack frame.
  3829.  
  3830.  
  3831.  86. Using 43-Line Mode with Hercules Card
  3832.  
  3833.  Product Version(s): 5.10   | 5.10
  3834.  Operating System:   MS-DOS | OS/2
  3835.  Flags: ENDUSER | SR# G880721-1772
  3836.  Last Modified: 27-JUL-1988    ArticleIdent: Q33403
  3837.  
  3838.     Currently, only 82x55 mode is supported for the Hercules card. It
  3839.  is possible to switch to 43-line mode if you first do a
  3840.  _setvideomode(_DEFAULTMODE), then immediately do a
  3841.  _setvideomode(_ERESCOLOR).
  3842.  
  3843.  
  3844.  
  3845.  87. Deeply Nested Blocks Cause C4073 Warning
  3846.  
  3847.  Product Version(s): 5.10   | 5.10
  3848.  Operating System:   MS-DOS | OS/2
  3849.  Flags: ENDUSER |
  3850.  Last Modified:  2-AUG-1988    ArticleIdent: Q33526
  3851.  
  3852.     The following program produces a C4073 warning when compiled with
  3853.  the CL /Zi filename.c command line:
  3854.  
  3855.  #include <assert.h>
  3856.  #include <process.h>
  3857.  #include <stdio.h>
  3858.  
  3859.  void main(ac,av)
  3860.  int ac;
  3861.  char **av;
  3862.  { assert(av[ac] == NULL);}
  3863.  
  3864.     The warning C4073 is generated when the compiler cannot generate
  3865.  symbolic information for separate lines of code that recognize the
  3866.  distinction between different blocks. For example, you may encounter
  3867.  this error if you have many deeply nested blocks, each of which declares
  3868.  automatic variables.
  3869.     The warning means that when in CodeView, the symbolic information
  3870.  at the deeper levels will be merged and you will be able to see the
  3871.  value of variables at lower levels when normally you would not.
  3872.     In this example, the warning is encountered because you are nesting
  3873.  three levels on the same line of code. The assert function actually
  3874.  is a macro that is expanded to two nested levels.
  3875.     You can work around the warning by moving the closing brace of the
  3876.  function to the next line.
  3877.  
  3878.  
  3879.  
  3880.  88. Glockenspiel Turbo Pascal to C Translator Source Code
  3881.  
  3882.  Product Version(s): 3.00 4.00 5.00 5.10
  3883.  Operating System:   MS-DOS
  3884.  Flags: ENDUSER |
  3885.  Last Modified: 12-OCT-1988    ArticleIdent: Q33561
  3886.  
  3887.     The Irish company Glockenspiel writes the Turbo Pascal to C
  3888.  Translator. If you are interested in obtaining the source code, please
  3889.  contact Glockenspiel. The following is the company's address and phone
  3890.  number:
  3891.  
  3892.     19 Belvedere Place
  3893.     Dublin 1
  3894.  
  3895.     011-353-1-364515
  3896.  
  3897.  
  3898.  89. Multiple Calls to ctime before Printing Results
  3899.  
  3900.  Product Version(s): 5.10   | 5.10
  3901.  Operating System:   MS-DOS | OS/2
  3902.  Flags: ENDUSER |
  3903.  Last Modified:  8-AUG-1988    ArticleIdent: Q33795
  3904.  
  3905.     The sample code below will print out the same time for the start and
  3906.  finish in the second printf statement; however, the statements should
  3907.  be printed two seconds apart. If ctime(&start) is taken out of the
  3908.  second printf statement, the finish time is later than the start time,
  3909.  as expected.
  3910.     As noted in the C Version 5.10 README.DOC, the ctime function uses
  3911.  a single static buffer to store the results of the call; i.e., when
  3912.  the second call to the function is made, the results of the first
  3913.  call are destroyed.  Therefore the behavior of the example is expected.
  3914.  
  3915.     The following sample code illustrates this behavior:
  3916.  
  3917.  time_t start, finish ;
  3918.  main() {
  3919.   time(&start) ;
  3920.   printf("the time is %s\n", ctime(&start) ) ;
  3921.   for ( i =0; i<1000; i++ )
  3922.      time(&finish) ;   /* start and finish should be about 2 sec apart */
  3923.   printf("ending time is %s and %s\n", ctime(&start), ctime(&finish) ) ;
  3924.  }
  3925.  
  3926.  
  3927.  90. C Version 5.10 LINK and Windows LINK4
  3928.  
  3929.  Product Version(s): 5.10    | 5.10
  3930.  Operating System:   MS-DOS | OS/2
  3931.  Flags: ENDUSER | SR# G880603-1453
  3932.  Last Modified:  8-AUG-1988    ArticleIdent: Q34029
  3933.  
  3934.     If you are developing Windows applications, you can use the
  3935.  Segemented Executable Linker provided with C Version 5.10.
  3936.     If you choose to use this linker for developing Windows
  3937.  applications, you must put the EXETYPE WINDOWS statement in your .DEF
  3938.  file. If you use LINK4, you do not have to put the EXETYPE WINDOWS
  3939.  statement in your .DEF file because the use of LINK4 causes the .EXE
  3940.  file to be identified as a Windows application.
  3941.  
  3942.  
  3943.  91. setvbuf with Buffer Greater than 32K Causes fwrite Failure
  3944.  
  3945.  Product Version(s): 5.00 5.10 | 5.10
  3946.  Operating System:   MS-DOS    | OS/2
  3947.  Flags: ENDUSER |
  3948.  Last Modified: 11-AUG-1988    ArticleIdent: Q34065
  3949.  
  3950.     The sample program below works correctly if the buffer size of the
  3951.  file is under 32K.  When the buffer size of the file is set higher
  3952.  than 32K (using setvbuf), the fwrite statement will fail and write
  3953.  "fwrite failed" to the screen. This problem occurs in Microsoft C
  3954.  Versions 5.00 and 5.10.
  3955.     Page 538 of the "Microsoft C 5.1 Optimizing Compiler Run Time
  3956.  Library Reference" manual indicates that the legal values for the size
  3957.  parameter are greater than zero and less than the maximum integer
  3958.  value (which is 32K). Therefore, even though the type for the
  3959.  size parameter is of type size_t (unsigned integer) only values
  3960.  less than 32K are correct for the size parameter to setvbuf().
  3961.     However, setvbuf should return an error for invalid size values.
  3962.  Microsoft is researching this problem and will post new information
  3963.  as it becomes available.
  3964.  
  3965.     The following sample code demonstrates this behavior:
  3966.  
  3967.  #include <stdio.h>
  3968.  
  3969.  char buf[35000] ;   /* size of file buffer */
  3970.  FILE *stream ;
  3971.  long result ;
  3972.  int err ;
  3973.  char i[10] = "abcdefghij" ;
  3974.  
  3975.  main() {
  3976.      stream = fopen("data1", "w+b") ;
  3977.      if ( err = setvbuf( stream, buf, _IOFBF, sizeof(buf) ) != 0)
  3978.          printf("failed to set buffer\n") ;
  3979.      else
  3980.          for ( result = 0; result < 5000; result++ )
  3981.              if (err = fwrite( i, sizeof(i), 1, stream )  != 1 ) {
  3982.                  printf("fwrite failed\n" ) ;
  3983.                  exit(-1) ;
  3984.                  }
  3985.  }
  3986.  
  3987.  
  3988.  92. Setting Size and Number of Internal Stacks
  3989.  
  3990.  Product Version(s): 3.x 4.x 5.00 5.10
  3991.  Operating System:   MS-DOS
  3992.  Flags: ENDUSER | s_quickc s_quickasm s_quickpas s_pascal
  3993.  Last Modified:  9-FEB-1990    ArticleIdent: Q58436
  3994.  
  3995.  If an INTERNAL STACK OVERFLOW system error occurs, the number and/or
  3996.  size of internal stacks in DOS should be increased in the CONFIG.SYS
  3997.  file. The syntax for this is as follows
  3998.  
  3999.     STACKS=number,size
  4000.  
  4001.  where number = number of stacks (8-64, default 9) and size = size of
  4002.  the stacks (32-512,default 128).
  4003.  
  4004.  The following information was taken from the MS-DOS Encyclopedia, Page
  4005.  805:
  4006.  
  4007.     Each time certain hardware interrupts occur, ... , MS-DOS Version
  4008.     3.2 switches to an internal stack before transferring control to
  4009.     the handler that will service the interrupt. In the case of
  4010.     nested interrupts, MS-DOS checks to ensure that both interrupts
  4011.     do not get the same stack. After the interrupt has been processed,
  4012.     the stack is released. This protects the stacks owned by
  4013.     application programs or system device drivers from overflowing when
  4014.     several interrupts occur in rapid succession.
  4015.     .
  4016.     .
  4017.     .
  4018.     If too many interrupts occur too quickly and the pool of internal
  4019.     stack frames is exhausted, the system halts with the message
  4020.     INTERNAL STACK OVERFLOW. Increasing the number parameter in the
  4021.     stacks command usually corrects the problem.
  4022.  
  4023.  
  4024.  93. Graphic Adapters Supported by the Graphics Routines
  4025.  
  4026.  Product Version(s): 5.10   | 5.10
  4027.  Operating System:   MS-DOS | OS/2
  4028.  Flags: ENDUSER |
  4029.  Last Modified: 11-AUG-1988    ArticleIdent: Q34068
  4030.  
  4031.     The following graphics adapters are supported by Microsoft C
  4032.  Version 5.10 and QuickC Version 1.01:
  4033.  
  4034.     Hercules card
  4035.  
  4036.     IBM adapters
  4037.     1. MDPA (Monochrome Display and Printer Adapter)
  4038.     2. CGA  (Color Graphics Adapter)
  4039.     3. EGA  (Enhanced Graphics Adapter)
  4040.     4. MCGA (Multi-Color Graphics Array)
  4041.     5. VGA (PS/2)  (Video Graphics Array)
  4042.        a. Analog monitors
  4043.     6. VGA (non-PS/2)
  4044.        a. Must be only adapter in system
  4045.        b. Use only monochrome modes with monochrome monitor
  4046.        c. Use only color modes with color monitor
  4047.  
  4048.     The Hercules card was not supported in previous versions of
  4049.  Microsoft C or QuickC.
  4050.  
  4051.  
  4052.  94. Putting Global Variables in the Default Data Segment
  4053.  
  4054.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  4055.  Operating System:   MS-DOS              | OS/2
  4056.  Flags: ENDUSER |
  4057.  Last Modified: 18-AUG-1988    ArticleIdent: Q34069
  4058.  
  4059.  Question:
  4060.     How can I tell the compiler to put my global variables in the
  4061.  default data segment when I am using the large- or huge-memory models?
  4062.  
  4063.  Response:
  4064.     In any memory model, if the near keyword is applied to global
  4065.  variables, they will be put in the default data segment. This action
  4066.  ensures that the variable is referenced with a 16-bit address, as
  4067.  opposed to the far 32-bit addresses, which will make variables defined
  4068.  with the near keyword faster to access.
  4069.  
  4070.  
  4071.  95. Converting from IEEE to MS binary format
  4072.  
  4073.  Product Version(s): 4.00 5.00 5.10 | 5.10
  4074.  Operating System:   MS-DOS         | OS/2
  4075.  Flags: ENDUSER |
  4076.  Last Modified: 12-OCT-1988    ArticleIdent: Q34070
  4077.  
  4078.  Question:
  4079.  
  4080.  How can I convert an IEEE number into Microsoft binary format?
  4081.  
  4082.  Response:
  4083.  
  4084.  The "Microsoft Run-Time Library Reference" manual contains
  4085.  documentation of four functions that are used to convert IEEE format
  4086.  to MS binary format and MS binary format to IEEE format.
  4087.  
  4088.  The four functions are as follows:
  4089.  
  4090.  fieeetomsbin: Converts a single precision floating-point
  4091.                number in IEEE format to MS binary format
  4092.  fmsbintoieee: Converts a single precision floating-point
  4093.                number in MS binary format to IEEE format
  4094.  dieeetomsbin: Converts a double precision number in IEEE
  4095.                format to MS binary format
  4096.  dmsbintoieee: Converts a double precision number in MS binary
  4097.                format to IEEE format
  4098.  
  4099.  
  4100.  96. Accessing Child Process Exit Code from Parent Process
  4101.  
  4102.  Product Version(s): 5.00 5.10
  4103.  Operating System:   MS-DOS
  4104.  Flags: ENDUSER | s_quickc s_quickasm
  4105.  Last Modified:  9-FEB-1990    ArticleIdent: Q58437
  4106.  
  4107.  Question:
  4108.  
  4109.  I am using the spawn() function and I want to be able to find out
  4110.  whether or not the child program terminated normally or by entry of
  4111.  CTRL+C. Is there anyway I can get the system exit code from the child
  4112.  process?
  4113.  
  4114.  Response:
  4115.  
  4116.  There is no C run-time function that will return the system exit code
  4117.  from a child process. However, Interrupt 21h SubFunction 4Dh can be
  4118.  used to return it.
  4119.  
  4120.  Immediately after a child process terminates, the child exit code and
  4121.  the system exit code are in the AL and AH registers respectively.
  4122.  
  4123.  Example:
  4124.  
  4125.                      _________________________
  4126.                      |           |           |
  4127.        AX Register   |     |     |     |     |
  4128.                      |           |           |
  4129.                      -------------------------
  4130.                           AH     |    AL
  4131.                           /            \
  4132.                          /              \
  4133.           System Exit Code               Child Exit Code
  4134.  
  4135.  When the spawn() family of functions is called with a mode flag of
  4136.  P_WAIT, only the child exit code is returned. To read the system exit
  4137.  code, a call to Interrupt 21h SubFunction 4Dh is needed.
  4138.  
  4139.  It is important to get and store the return codes immediately upon
  4140.  returning from the child process, since another function may modify
  4141.  them.
  4142.  
  4143.  The following code samples demonstrate how to get the exit code from
  4144.  the child process within the parent process with C Version 5.10 and
  4145.  QuickC Versions 2.00 and 2.01.
  4146.  
  4147.  Code Example 1
  4148.  --------------
  4149.  
  4150.  /* Call this prog1.c  */
  4151.  #include <dos.h>
  4152.  #include <stdio.h>
  4153.  #include <process.h>
  4154.  
  4155.  union REGS inregs, outregs, tempreg;
  4156.  int retcode;
  4157.  unsigned char syscode;
  4158.  
  4159.  void main (void)
  4160.  {
  4161.     printf ("In program I\n");
  4162.     retcode = spawnl (P_WAIT, "sp2.exe", "sp2", NULL);
  4163.  
  4164.     /* Call int 21h function 4Dh to obtain exit codes */
  4165.  
  4166.     inregs.h.ah = 0x4d;
  4167.     intdos (&inregs, &outregs);
  4168.  
  4169.     /* System Exit Code will be in AH. */
  4170.  
  4171.     syscode = outregs.h.ah;
  4172.  
  4173.     printf ("Child exit code: %d\n", retcode);
  4174.     printf ("Child process ");
  4175.     switch (syscode)
  4176.     {
  4177.        case 0 : printf ("terminated normally\n");
  4178.                 break;
  4179.        case 1 : printf ("exit with a Control-C\n");
  4180.                 break;
  4181.        case 2 : printf ("exit with a hard error\n");
  4182.                 break;
  4183.        case 3 : printf ("exit as a TSR program\n");
  4184.                 break;
  4185.     }
  4186.  }
  4187.  
  4188.  Code Example 2
  4189.  --------------
  4190.  
  4191.  /* Call this sp2.c */
  4192.  #include <stdio.h>
  4193.  
  4194.  void main (void)
  4195.  {
  4196.     printf ("In program II\n");
  4197.     exit (77);
  4198.  }
  4199.  
  4200.  Since QuickC 2.00 and QuickAssembler 2.01 have the feature of using
  4201.  inline assembly, the AX register can be access directly without using
  4202.  any interrupts. The following line of code can be used in place of the
  4203.  interrupt call:
  4204.  
  4205.  _asm mov syscode, ah
  4206.  
  4207.  
  4208.  97. Link Error L1073
  4209.  
  4210.  Product Version(s): 5.01.21 5.01.20
  4211.  Operating System:   MS-DOS
  4212.  Flags: ENDUSER |
  4213.  Last Modified: 11-AUG-1988    ArticleIdent: Q34142
  4214.  
  4215.     The linker error L1073 is documented in the CodeView and Utilities
  4216.  update section of the manuals for MASM Version 5.10, C Version 5.10,
  4217.  FORTRAN Version 4.10, and Pascal Version 4.00. The error message is as
  4218.  follows:
  4219.  
  4220.     L1073 file-segment limit exceeded.
  4221.  
  4222.     The number of physical file segments exceeds the limit of 254
  4223.  imposed by OS/2 protected mode and by Windows for each application or
  4224.  dynamic-link library. (A file segment is created for each group
  4225.  definition, nonpacked logical segment, and set of packed segments.)
  4226.     Reduce the number of segments or group more of them, making sure
  4227.  /PACKCODE is enabled.
  4228.  
  4229.  
  4230.  98. Clock: C Function -- Documentation Supplement
  4231.  
  4232.  Product Version(s): 5.10   |  5.10
  4233.  Operating System:   MS-DOS |  OS/2
  4234.  Flags: ENDUSER | S_QuickC S_QuickAsm docsup
  4235.  Last Modified: 17-JUL-1990    ArticleIdent: Q49729
  4236.  
  4237.  The clock function is documented as telling how much processor time
  4238.  has been used by the calling process. This definition is misleading.
  4239.  
  4240.  The clock function returns a clock_t (long) value, which is the
  4241.  difference between the time field (for seconds) and millitm field (for
  4242.  milliseconds) in the structure that is returned from two calls to the
  4243.  ftime function. The first call to ftime is made within the start-up
  4244.  code of the executing program, and the second call is made when the
  4245.  clock function is explicitly called in your code.
  4246.  
  4247.  This means that the value returned by clock is the number of CLK_TCKs
  4248.  (milliseconds) elapsed since the start-up code was executed, or -1 if
  4249.  the function was unsuccessful.
  4250.  
  4251.  Note: On most IBM PCs and compatibles, the clock speed is not fast
  4252.  enough to compute milliseconds, or indeed, hundredths of seconds. The
  4253.  ftime function calls interrupt 21, function 2Ch (under DOS), which
  4254.  returns, among other information, the seconds in hundredths. The
  4255.  hundredths information is an estimation from the clock speed, which is
  4256.  approximately 18.2 ticks per second on most PCs. This hundredths value
  4257.  is multiplied by 10 to get the millisecond value.
  4258.  
  4259.  Below is information on resetting the initial time value.
  4260.  
  4261.  The clock function references an external variable called _citime.
  4262.  This causes _cinitim.asm to get linked in to the .EXE, which in turn
  4263.  enters a function called _inittime into the start-up initialization
  4264.  table.
  4265.  
  4266.  The _inittime function, which is then called by the start-up code,
  4267.  simply makes a call to the ftime function, passing it a static timeb
  4268.  structure. Any further calls to the clock function subtract the values
  4269.  in this structure from the values in the structure returned by the
  4270.  ftime call in the clock function.
  4271.  
  4272.  In some cases, you might want to know the time elapsed between two or
  4273.  more internal points in a program. To reset the initial time value,
  4274.  make a call to the function _inittime, which makes a call to ftime,
  4275.  resetting the initial time structure to the current time. All
  4276.  subsequent calls to the clock function return the elapsed time since
  4277.  the last _inittime call.
  4278.  
  4279.  Other sources of information include the Version 5.10 "Microsoft C for
  4280.  the MS-DOS Operating System: Run-Time Library Reference," Page 167 and
  4281.  the clock function in the "C Run-Time Library Source Routines," which
  4282.  is available as a separate package.
  4283.  
  4284.  
  4285.  99. C4040 Occurs on Declaration of Huge Array
  4286.  
  4287.  Product Version(s): 4.00 5.00 5.10 | 5.10
  4288.  Operating System:   MS-DOS         | 5.10
  4289.  Flags: ENDUSER |
  4290.  Last Modified: 17-AUG-1988    ArticleIdent: Q34170
  4291.  
  4292.     The compiler warning "C4040 near/far/huge on identifier ignored"
  4293.  occurs on the declaration of a huge array if the array is not
  4294.  declared globally or statically. A huge or far array only can be
  4295.  declared at the global (or static) level because local (auto)
  4296.  variables are allocated on the stack and cannot be far or huge.
  4297.     To ensure that your arrays are allocated as huge or far arrays,
  4298.  declare them at the global level or declare them with the static
  4299.  storage class.
  4300.  
  4301.  
  4302.  100. Splitpath Document Error in readme.doc
  4303.  
  4304.  Product Version(s): 5.10   | 5.10
  4305.  Operating System:   MS-DOS | OS/2
  4306.  Flags: ENDUSER | docerr
  4307.  Last Modified: 12-OCT-1988    ArticleIdent: Q34172
  4308.  
  4309.     The documentation in the C Version 5.10 readme.doc about the
  4310.  document error in the run-time library reference is incorrect. The
  4311.  documentation says the following:
  4312.  
  4313.          char * ext[4]
  4314.  
  4315.   should read
  4316.  
  4317.          char * ext[5]
  4318.  
  4319.     The documentation should say the following:
  4320.  
  4321.    should read
  4322.  
  4323.          char ext[5]
  4324.  
  4325.     In addition, drive, dir, fname, and ext should not have asterisks
  4326.  (stars, "*"'s) in front of them either.  A proper declaration is:
  4327.  
  4328.      char path_buffer[40], drive[3], dir[30], fname[9], ext[5];
  4329.  
  4330.  
  4331.  101. Path Strings Need Double Backslashes or fopen/open Fails
  4332.  
  4333.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  4334.  Operating System:   MS-DOS              | OS/2
  4335.  Flags: ENDUSER |
  4336.  Last Modified: 27-OCT-1988    ArticleIdent: Q34305
  4337.  
  4338.  Problem:
  4339.  
  4340.  According to Pages 444 and 274 of the "Microsoft C 5.10 Optimizing
  4341.  Compiler Run-Time Library Reference," I should be able to specify the
  4342.  path to the file that I want to open. However, I always receive a null
  4343.  pointer, indicating an error, when I attempt to open a file that is
  4344.  not in the current directory.
  4345.  
  4346.  I am using the following fopen statement:
  4347.  
  4348.  stream = fopen("d:\c\source\test.c", "r");
  4349.  
  4350.  Response:
  4351.  
  4352.  The following fopen statement will successfully open the file:
  4353.  
  4354.  stream = fopen("d:\\c\\source\\test.c", "r");
  4355.  
  4356.  Because the backslash has special meaning in C, it must be preceded by
  4357.  an additional backslash. In the case of the first (unsuccessful)
  4358.  example, a file named "d:csourcetest.c" actually is being searched for
  4359.  in the current directory. In the second example, the correct directory
  4360.  is searched for in the file "test.c".
  4361.  
  4362.  The following other functions are among those that use path names as
  4363.  input arguments:
  4364.  
  4365.  chdir, mkdir, rmdir, access, chmod, remove, rename, splitpath, stat,
  4366.  creat,  open, sopen, freopen, tempnam, execl, execle, execlp,
  4367.  execlpe, execv, execve, execvp, execvpe, spawnl, spawnle, spawnlp,
  4368.  spawnlpe, spawnv, spawnve, spawnvp, spawnvpe, system, _dos_creat,
  4369.  _dos_creatnew, _dos_findfirst, _dos_getfileattr, _dos_open,
  4370.  _dos_setfileattr, utime, putenv, _searchenv
  4371.  
  4372.  
  4373.  102. Manual-Setup Procedure for C
  4374.  
  4375.  Product Version(s): 5.00 5.10 | 5.10
  4376.  Operating System:   MS-DOS    | OS/2
  4377.  Flags: ENDUSER |
  4378.  Last Modified: 11-JAN-1990    ArticleIdent: Q34310
  4379.  
  4380.  The following is a manual-setup procedure for C.
  4381.  
  4382.  Manual Setup Procedure For Microsoft C (DOS only) System
  4383.  Configurations:
  4384.  
  4385.  Directory:
  4386.  
  4387.  C:\MSC\BIN                  Executable file (*.EXE)
  4388.  C:\MSC\LIB                  Library and Object modules (*.LIB, *.OBJ)
  4389.  C:\MSC\INCLUDE              Include (or header) files (*.H)
  4390.  C:\MSC\SRC                  Sample C programs
  4391.  C:\MSC\UTILS                Utilities, such as LINK.EXE, CV.EXE ect.
  4392.  C:\MSC\INIT                 Initialization files (*.INI)
  4393.  C:\MSC\TEMP                 Temporary files for the C compiler only
  4394.                              No files copied into this directory
  4395.  
  4396.  Autoexec.bat:
  4397.  
  4398.  SET LIB=C:\MSC\LIB
  4399.  SET INCLUDE=C:\MSC\INCLUDE
  4400.  SET TMP=C:\MSC\TEMP
  4401.  SET INIT=C:\MSC\INIT
  4402.  SET PATH=C:\MSC\UTILS;C:\MSC\BIN;C:\MSC\SRC
  4403.  
  4404.  Config.sys:
  4405.  
  4406.  Files=20
  4407.  Buffers=20
  4408.  Shell=C:\Command.com /e: 1024 /p
  4409.  
  4410.  (Note that the above use of the Shell command is typically only
  4411.  supported for DOS Versions 3.20 and later.)
  4412.  
  4413.  Files to Copy:
  4414.  
  4415.  Copy the following files into the C:\MSC\BIN directory:
  4416.  
  4417.  C1.EXE      C1L.EXE
  4418.  C2.EXE      MOUSE.COM
  4419.  C3.EXE      QCL.HLP
  4420.  CL.EXE      C23.ERR
  4421.  QC.EXE      QC.HLP
  4422.  QCL.EXE
  4423.  
  4424.  Copy all the INCLUDE files with .H extensions into the C:\MSC\INCLUDE
  4425.  directory.
  4426.  
  4427.  Copy the following files into the C:\MSC\UTILS directory:
  4428.  
  4429.  LINK.EXE
  4430.  M.EXE
  4431.  LIB.EXE
  4432.  CV.EXE
  4433.  CV.HLP
  4434.  Any other utilities, such as EXEMOD.EXE
  4435.  
  4436.  Copy the following files into the C:\MSC\INIT directory:
  4437.  
  4438.  TOOLS.INI
  4439.  Any other .INI file
  4440.  
  4441.  Copy any C sample programs provided with the compiler into the
  4442.  C:\MSC\SRC directory.
  4443.  
  4444.  Running The Library Manager -- LIB.EXE:
  4445.  
  4446.  The following section assumes that the above configurations where
  4447.  followed and the operations completed. The following section is on
  4448.  libraries.
  4449.  
  4450.  The C linker searches the C:\MSC\LIB directory to find either C
  4451.  combined libraries or explicitly named libraries. The Microsoft naming
  4452.  convention for combined libraries is xLIByz.LIB. x is either S, M, C,
  4453.  or L for Small, Medium, Compact, or Large, respectively. y is the
  4454.  language, in this case C. z is the math libraries; A, E, 7 for
  4455.  Alternate, Emulation, or 87 coprocessor, respectively.
  4456.  
  4457.  The following is an example:
  4458.  
  4459.  MLIBCE.LIB  is the (M)edium model, (C) (E)mulation combined library
  4460.  
  4461.  Copy the following files into the C:\MSC\LIB directory:
  4462.  
  4463.  xLIBy.lib
  4464.  sDLIBC.LIB          Depending on what is desired
  4465.  mLIBC.LIB
  4466.  cLIBC.LIB
  4467.  lLIBC.LIB
  4468.  EM.LIB or 87.LIB    Depending on what is desired, none for alt. math
  4469.  xLIBFz.LIB          z is A for alternate or P for other
  4470.  sLIBFz.LIB          Depending on choice above
  4471.  mLIBFz.LIB
  4472.  cLIBFz.LIB
  4473.  lLIBFz.LIB
  4474.  LIBH.LIB
  4475.  GRAPHICS.LIB        ( Optional )
  4476.  
  4477.  The following is an example of how to run the library manager:
  4478.  
  4479.  1. At the operating system prompt, type LIB, then the name you
  4480.     want to call the library with the .LIB extension.
  4481.  
  4482.  2. Press the ENTER key. The prompt will say OPERATIONS.
  4483.  
  4484.  3. Enter the desired operations, such as appending stand alone .LIB
  4485.     or .OBJ files. If the number of modules is too many for one text
  4486.     line, the at sign, "@", can be used as a continuation character.
  4487.  
  4488.  4. A list ( *.LST ) file is asked for, which is optional.
  4489.  
  4490.  The following example demonstrates this process:
  4491.  
  4492.          C:\> LIB name.lib
  4493.               Operations: +mod1.lib + mod2.lib + ... +modk.lib@
  4494.               Operations: +...+ modn.lib
  4495.               List File: name.lst
  4496.  
  4497.  Name.lst contains a listing of all the functions that occur in
  4498.  name.lib.
  4499.  
  4500.  The following is an example of how to build the C Medium model,
  4501.  Emulation library with graphics:
  4502.  
  4503.     C:\> LIB mlibce.lib
  4504.     Operations: +mlibc.lib +em.lib +mlibfp.lib +libh.lib +graphics.lib
  4505.     List File: <ENTER>  ( pressing enter here will suppress the
  4506.                                     creation of a listing file. )
  4507.  
  4508.  The above example can be repeated with appropriate modifications to
  4509.  create the other C combined libraries.
  4510.  
  4511.  
  4512.  103. Documentation Error Regarding Precedence Operators
  4513.  
  4514.  Product Version(s): 5.00 5.10 | 5.10
  4515.  Operating System:   MS-DOS    | OS/2
  4516.  Flags: ENDUSER | docerr
  4517.  Last Modified: 12-OCT-1988    ArticleIdent: Q34360
  4518.  
  4519.     There is a documentation error regarding C Version 5.00 and Version
  4520.  5.10 operator precedence. Table 5.1 on Page 137 of the "Microsoft C
  4521.  Language Reference Manual" shows two curly braces. Both of these curly
  4522.  braces are over-extended in printing.
  4523.     The curly brace at the top should only extend from the second line
  4524.  to the third line; the curly brace at the bottom should start at the
  4525.  fourth-to-last line and stop at the second-to-last line.
  4526.  
  4527.  
  4528.  104. Unresolved Externals Link Errors for OS/2 Calls
  4529.  
  4530.  Product Version(s): 5.10   | 5.10
  4531.  Operating System:   MS-DOS | OS/2
  4532.  Flags: ENDUSER |
  4533.  Last Modified: 20-OCT-1988    ArticleIdent: Q34372
  4534.  
  4535.  Question:
  4536.  
  4537.  Why do I get unresolved externals for all of my API calls when I link
  4538.  object files produced by the C Version 5.10 compiler?
  4539.  
  4540.  Response:
  4541.  
  4542.  You can control the OS/2 files to include by defining certain symbols
  4543.  in your source code. A few of the more common ones are listed below:
  4544.  
  4545.  #define INCL_BASE        /*  all OS/2 base definitions        */
  4546.  #define INCL_DOS         /*  OS/2 DOS kernel                  */
  4547.  #define INCL_SUB         /*  VIO, keyboard, mouse functions   */
  4548.  #define INCL_DOSERRORS   /*  OS/2 errors                      */
  4549.  
  4550.  One or more of the above definitions should be followed by the
  4551.  following:
  4552.  
  4553.  #include <os2.h>
  4554.  
  4555.  The above #defines and #include preprocessor directives will start a
  4556.  chain reaction of #defines and #includes that will define the API
  4557.  functions in the respective categories of functions. You can follow
  4558.  this series to determine the minimum prototypes required for the API
  4559.  functions called by your application.
  4560.  
  4561.  If the proper constant is not defined in your source code above the
  4562.  line where you include OS2.H, there will be no prototypes for API
  4563.  functions.
  4564.  
  4565.  All of the API functions must be declared with the Pascal calling
  4566.  convention. If there are no prototypes to tell the compiler to use the
  4567.  Pascal calling convention, the compiler will use the default C calling
  4568.  convention. The C calling convention will place an underscore (_) in
  4569.  front of each function called; therefore, each function will be
  4570.  incorrectly named, resulting in unresolved externals at link time. The
  4571.  Pascal calling convention does not place an underscore in front of
  4572.  each function, so if the correct prototypes are given, the linker will
  4573.  resolve all of the references to the API functions in the DOSCALLS.LIB
  4574.  library.
  4575.  
  4576.  This information is documented in the README.DOC file that comes with
  4577.  Microsoft C Version 5.10.
  4578.  
  4579.  
  4580.  105. Maximum of 40 File Handles in C 5.10 Multi-Thread Programs
  4581.  
  4582.  Product Version(s): 5.10   | 5.10
  4583.  Operating System:   MS-DOS | OS/2
  4584.  Flags: ENDUSER |
  4585.  Last Modified: 12-OCT-1988    ArticleIdent: Q34386
  4586.  
  4587.  Question:
  4588.     Can I increase the number of file handles to more than 40
  4589.  in a multi-threaded application produced by C Version 5.10?
  4590.  
  4591.  Response:
  4592.     The maximum number of file handles available for multiple-threaded
  4593.  applications is 40 by default; this number cannot be increased because
  4594.  the multi-threaded startup code is unavailable. Consequently, the C
  4595.  startup code constant _NFILE_, which is used to specify the number of
  4596.  available file handles, cannot be changed from its default of 40, even
  4597.  though the default number of file handles in OS/2 is 255.
  4598.  
  4599.  
  4600.  
  4601.  106. _getimage() Buffer Format is Proprietary
  4602.  
  4603.  Product Version(s): 5.00 5.10
  4604.  Operating System:   MS-DOS
  4605.  Flags: ENDUSER |
  4606.  Last Modified: 18-DEC-1989    ArticleIdent: Q34388
  4607.  
  4608.  Question:
  4609.     What is the internal representation of the screen image saved by
  4610.  the _getimage C run-time library function for DOS?
  4611.  
  4612.  Response:
  4613.     Microsoft does not currently release information on the internal
  4614.  representation of graphic images saved by _getimage.
  4615.  
  4616.  
  4617.  107. Far Pointer Comparisons Assume Same Segment
  4618.  
  4619.  Product Version(s): 5.10   | 5.10
  4620.  Operating System:   MS-DOS | OS/2
  4621.  Flags: ENDUSER |
  4622.  Last Modified: 12-OCT-1988    ArticleIdent: Q34408
  4623.  
  4624.  When comparing Far pointers with the <, >, <=, or >= operators, the
  4625.  two pointers must be in the same segment. The equality operator (==)
  4626.  tests both segment and offset to prevent two pointers that have the
  4627.  same offset but different segments from being considered equal.
  4628.  
  4629.  The <, >, <=, and >= operators assume that the pointer share the same
  4630.  segment because according to the Draft proposed ANSI C standard,
  4631.  pointers can only be compared for precedence if they point to the same
  4632.  object. In a segmented architecture such as Intel's, two pointers to
  4633.  the same object must share the same segment value (unless the
  4634.  pointers are declared to point to a huge object, in which case
  4635.  the pointers are handled using 32-bit arithmetic).
  4636.  
  4637.  
  4638.  108. Far Pointer Comparisons Don't Account for Aliases
  4639.  
  4640.  Product Version(s): 5.10   | 5.10
  4641.  Operating System:   MS-DOS | OS/2
  4642.  Flags: ENDUSER |
  4643.  Last Modified: 12-OCT-1988    ArticleIdent: Q34410
  4644.  
  4645.  The code generated to compare two far pointers for equality does not
  4646.  account for the possibility of the pointers having different segments
  4647.  and offsets, yet still pointing to the same location.
  4648.  
  4649.  This is correct behavior for the compiler. Only huge pointers are
  4650.  normalized. Near and Far pointers that point into the same segment are
  4651.  assumed to have the same segment values; any differences between them
  4652.  must be in the offset.
  4653.  
  4654.  Normalizing pointers would involve a tremendous performance penalty
  4655.  under MS-DOS and would be impossible under OS/2 due to the
  4656.  protected-mode addressing scheme.
  4657.  
  4658.  
  4659.  109. LINT_ARGS Is Predefined in C Versions 5.x
  4660.  
  4661.  Product Version(s): 5.00 5.10 | 5.10
  4662.  Operating System:   MS-DOS    | OS/2
  4663.  Flags: ENDUSER |
  4664.  Last Modified: 18-AUG-1988    ArticleIdent: Q34437
  4665.  
  4666.  The special identifier LINT_ARGS, which enables type checking, is
  4667.  predefined in Microsoft C Versions 5.00 and later. No preprocessor
  4668.  directive or compile option is needed to define this identifier.
  4669.  
  4670.  Microsoft C Version 4.00 provides the option to enable type checking
  4671.  on C run-time library function calls. To enable this option in C
  4672.  Version 4.00, define the special identifier LINT_ARGS either by
  4673.  placing a #define directive before any #include directives for include
  4674.  files that contain run-time library function declarations, or by using
  4675.  the /DLINT_ARGS (or /D LINT_ARGS) compilation option.
  4676.  
  4677.  Defining LINT_ARGS makes the function declarations available that are
  4678.  enclosed in preprocessor #ifdefined() blocks and that are included
  4679.  only if LINT_ARGS is defined.
  4680.  
  4681.  
  4682.  110. Installing C on a Network Violates License Agreement
  4683.  
  4684.  Product Version(s): 5.10   | 5.10
  4685.  Operating System:   MS-DOS | OS/2
  4686.  Flags: ENDUSER |
  4687.  Last Modified: 12-OCT-1988    ArticleIdent: Q34445
  4688.  
  4689.  Installing software from the C, FORTRAN, Macro Assembler, Pascal, or
  4690.  Quick C retail packages on a network is prohibited by the Microsoft
  4691.  License Agreement.
  4692.  
  4693.  These applications are single-user products; network versions of them
  4694.  are unavailable at this time.
  4695.  
  4696.  
  4697.  
  4698.  111. Library Reference Defines Unused result Pointer
  4699.  
  4700.  Product Version(s): 5.00 5.10 | 5.10
  4701.  Operating System:   MS-DOS    | OS/2
  4702.  Flags: ENDUSER | docerr
  4703.  Last Modified: 12-OCT-1988    ArticleIdent: Q34520
  4704.  
  4705.  The program example for qsort on Page 476 in the "Microsoft C
  4706.  Optimizing Compiler Run-Time Library Reference" has a documentation
  4707.  error. The following first declaration within the main function, is
  4708.  unnecessary:
  4709.  
  4710.  char **result;
  4711.  
  4712.  The result pointer is never used in the program.
  4713.  
  4714.  
  4715.  112. "User's Guide" Index Reference for /F Is Page 122 Not Page 123
  4716.  
  4717.  Product Version(s): 5.00 5.10 | 5.10
  4718.  Operating System:   MS-DOS    | OS/2
  4719.  Flags: ENDUSER | docerr
  4720.  Last Modified: 12-OCT-1988    ArticleIdent: Q34567
  4721.  
  4722.  The "Microsoft C Optimizing Compiler User's Guide" index has a
  4723.  typographical error. The page reference for "/F option" is given as
  4724.  Page 123; however, it should be Page 122.
  4725.  
  4726.  
  4727.  113. Run-Time Limits for C Version 5.10
  4728.  
  4729.  Product Version(s): 5.10   | 5.10
  4730.  Operating System:   MS-DOS | OS/2
  4731.  Flags: ENDUSER |
  4732.  Last Modified: 12-OCT-1988    ArticleIdent: Q34856
  4733.  
  4734.  The following is a table of run-time limits in the Microsoft C
  4735.  Compiler Version 5.10:
  4736.  
  4737.  Program Limits at Run Time
  4738.  
  4739.  Item            Description                 Limit
  4740.  
  4741.  Files           Maximum file size           (2**32) - 1 bytes
  4742.                                              (i.e., 4 gigabytes)
  4743.          (or limit imposed by DOS, 32 megabytes
  4744.          as of DOS 3.3)
  4745.  
  4746.                  Maximum number
  4747.                  of open files (streams)     20
  4748.                  (Five streams are opened automatically (stdin,
  4749.                  stdout, stdaux, and stdprn), leaving 15 files
  4750.                  available for the program to open.
  4751.          Instructions for increasing this limit up to 127 are
  4752.          included in the README.DOC of Version 5.10.)
  4753.  
  4754.  Command line    Maximum number of           128
  4755.                  characters(including
  4756.                  program name)
  4757.  
  4758.  Environment     Maximum size                32K
  4759.  table
  4760.  
  4761.  This table is listed on Page 286 of the user's guide contained
  4762.  in the "Microsoft C 5.1 Optimizing Compiler" manual.
  4763.  
  4764.  
  4765.  114. C4047 Occurs when Function Prototype Is Omitted or Misnamed
  4766.  
  4767.  Product Version(s): 5.00 5.10 | 5.10
  4768.  Operating System:   MS-DOS    | OS/2
  4769.  Flags: ENDUSER |
  4770.  Last Modified: 26-AUG-1988    ArticleIdent: Q34859
  4771.  
  4772.  The compiler warning message
  4773.  
  4774.  "C4047 'operator' : different levels of indirection"
  4775.  
  4776.  can occur when a function prototype declaration is not specified, when
  4777.  the header file that contains the declaration is not given in a
  4778.  #include directive, when a reference to a function is misspelled,
  4779.  or when a pointer is assigned a value of a different type without
  4780.  using an appropriate type cast.
  4781.  
  4782.  When the function declaration is omitted, a default prototype is
  4783.  created with a return type of int assumed. A later use of the function
  4784.  then may cause the C4047 warning, such as assigning the return value
  4785.  of the function to a non-int variable.
  4786.  
  4787.  If the call to the function is not spelled the same as the name of the
  4788.  prototype, the prototype will not be referred to, the default
  4789.  assumption for the function return type will be int, and the warning
  4790.  may occur.
  4791.  
  4792.  More information on function prototyping can be found beginning on
  4793.  Page 169 in Chapter 7 of the "Microsoft C Optimizing Compiler Language
  4794.  Reference" manual.
  4795.  
  4796.  
  4797.  115. Array Reference Gives "C4046 '&' on Function/Array, Ignored"
  4798.  
  4799.  Product Version(s): 5.00 5.10 | 5.10
  4800.  Operating System:   MS-DOS    | OS/2
  4801.  Flags: ENDUSER |
  4802.  Last Modified: 26-AUG-1988    ArticleIdent: Q34905
  4803.  
  4804.  The following compiler warning message occurs when an array is
  4805.  referred to incorrectly by the address-of operator (&).
  4806.  
  4807.  C4046 '&' on function/array, ignored
  4808.  
  4809.  The following program causes the warning C4046:
  4810.  
  4811.  void main(void);
  4812.  void main(void)
  4813.  {
  4814.   char array[10];
  4815.   char *ptr_to_array;
  4816.   ptr_to_array = &array;
  4817.  }
  4818.  
  4819.  To clear up the warning, make the assignment read either
  4820.  
  4821.  ptr_to_array = array;
  4822.  
  4823.  or
  4824.  
  4825.  ptr_to_array = &array[0];
  4826.  
  4827.  More information about arrays can be found in the last paragraph on
  4828.  Page 104 and in Example 1 on Page 119 of the "Microsoft C Optimizing
  4829.  Compiler Language Reference" manual.
  4830.  
  4831.  
  4832.  116. Run-Time Library Reference _getfillmask, _setfillmask docerrs
  4833.  
  4834.  Product Version(s): 5.00 5.10 | 5.10
  4835.  Operating System:   MS-DOS    | 5.10
  4836.  Flags: ENDUSER | docerr
  4837.  Last Modified: 26-AUG-1988    ArticleIdent: Q34906
  4838.  
  4839.  The program examples for _getfillmask and _setfillmask, on Pages
  4840.  325-326 and Pages 521-522 of the "Microsoft C 5.1 Optimizing Compiler
  4841.  Run-Time Library Reference" have an error. The fill mask array is
  4842.  incorrectly initialized. Back slashes are required prior to "x" for
  4843.  specifying hexadecimal constants for the char variables of the masks.
  4844.  
  4845.  The following sample code correctly initializes the char variables:
  4846.  
  4847.  #include <stdio.h>
  4848.  #include <graph.h>
  4849.  
  4850.  unsigned char *(style[6])={"\x78\x30\x30\x78\x30\x30\x78\x30",
  4851.                             "\x78\x32\x30\x78\x30\x38\x78\x32",
  4852.                             "\x78\x39\x38\x78\x63\x36\x78\x33",
  4853.                             "\x78\x65\x36\x78\x33\x38\x78\x62",
  4854.                             "\x78\x66\x63\x78\x65\x65\x78\x37",
  4855.                             "\x78\x66\x65\x78\x66\x65\x78\x66"};
  4856.  
  4857.  char *oldstyle = "12345678"; /* place holder for old style */
  4858.  
  4859.  main()
  4860.  {
  4861.   int loop;
  4862.   _setvideomode(_MRES4COLOR);
  4863.   _getfillmask( oldstyle );
  4864.   _setcolor( 2 ); /* draw an ellipse under the */
  4865.   /* middle few rectangles in a different color */
  4866.   _ellipse( _GFILLINTERIOR, 120, 75, 200, 125 );
  4867.   _setcolor( 3 );
  4868.   for ( loop = 0; loop < 6; loop++ ) {
  4869.   /* make 6 rectangles, the first background color */
  4870.   _setfillmask( (char far *)(style[ loop ]) );
  4871.   _rectangle(_GFILLINTERIOR,loop*40+5,90,(loop+1)*40,110);
  4872.   }
  4873.   _setfillmask( oldstyle ); /* restore old style */
  4874.   while ( !kbhit() ); /* Strike any key to continue */
  4875.   _setvideomode (_DEFAULTMODE);
  4876.  }
  4877.  
  4878.  
  4879.  117. Mixed Expressions Can Cause Unsigned Division
  4880.  
  4881.  Product Version(s): 5.10   | 5.10
  4882.  Operating System:   MS-DOS | OS/2
  4883.  Flags: ENDUSER |
  4884.  Last Modified: 12-OCT-1988    ArticleIdent: Q34920
  4885.  
  4886.  The ANSI C standard specifies that when a signed and unsigned integer
  4887.  are involved in an arithmetic expression, the signed integer is to be
  4888.  converted to the type of the unsigned before expression evaluation. If
  4889.  the signed integer is negative, the sign will be lost and the value
  4890.  will change, even though the bit pattern will remain the same.
  4891.  
  4892.  This situation is especially a problem with functions that return a
  4893.  value of type size_t, which is an alias for unsigned int in our
  4894.  implementation. Note that this is not a problem or a code generation
  4895.  error, this is the expected behavior.
  4896.  
  4897.  For example, if the statement
  4898.  
  4899.  i = (4 - strlen("1234567890")) / 2;
  4900.  
  4901.  is executed, the value of i will be 32765 rather than -3 as one might
  4902.  expect because the expression (4 - strlen("1234567890")) is an
  4903.  unsigned integer expression with the value of 65530 rather than a
  4904.  signed expression with the value of -6. If you look at the code
  4905.  generated, you'll notice that an instruction that performs unsigned
  4906.  division is generated rather than a one that performs signed division.
  4907.  
  4908.  To avoid this behavior, use a typecast on the return value
  4909.  of strlen() so that it is treated as an int. For the example
  4910.  above, the statement
  4911.  
  4912.  i = (4 - (int) strlen("1234567890")) / 2;
  4913.  
  4914.  would have generated the desired value of -3. Note that even this code
  4915.  would have failed if the length of the string was greater than 32767;
  4916.  however, the incorrect code above fails if the length of the string is
  4917.  greater than four.
  4918.  
  4919.  Runtime functions that return values of type size_t, unsigned, or
  4920.  unsigned long include the following:
  4921.  
  4922.  strtoul, _getlinestyle, fread, fwrite, _clear87, _control87,
  4923.  _status87, _fmsize, _memavl, _memmax, _msize, _nmsize,
  4924.  stackavail, strcspn, strlen, strspn, _bios_disk,
  4925.  _bios_equiplist, _bios_keybrd, _bios_memsize, _bios_printer,
  4926.  _bios_serialcom, _bios_timeofday, _dos_allocmem, _dos_close,
  4927.  _dos_creat, _dos_creatnew, _dos_findfirst, _dos_findnext,
  4928.  _dos_freemem, _dos_getdate, _dos_getdiskfree,
  4929.  _dos_getfileattr, _dos_getftime, _dos_gettime, _dos_open,
  4930.  _dos_read, _dos_setblock, _dos_setdate, _dos_setfileattr,
  4931.  _dos_setftime, _dos_settime, _dos_write, FP_OFF, FP_SEG,
  4932.  long_lrotl, long_lrotr, _rotl, and _rotr
  4933.  
  4934.  
  4935.  118. The Proper Type for Pointer To jmp_buf Is void *
  4936.  
  4937.  Product Version(s): 5.00 5.10 | 5.10
  4938.  Operating System:   MS-DOS    | OS/2
  4939.  Flags: ENDUSER |
  4940.  Last Modified: 12-OCT-1988    ArticleIdent: Q34921
  4941.  
  4942.  The setjmp() and longjmp() functions use a parameter of type jmp_buf.
  4943.  (The type jmp_buf is declared in setjmp.h.) Using the & operator
  4944.  ("address of") on a variable of type jmp_buf generates the following
  4945.  message:
  4946.  
  4947.  warning C4046: '&' on function/array, ignored
  4948.  
  4949.  Leaving the ampersand (&) off and assigning the value to a
  4950.  variable badptr declared, as follows
  4951.  
  4952.  set_jmp *bad_ptr;
  4953.  
  4954.  generates the following message:
  4955.  
  4956.  warning C4047: '=' : different levels of indirection
  4957.  
  4958.  To solve the problem, declare the pointer to be of type void *,
  4959.  as follows:
  4960.  
  4961.  void *goodptr;
  4962.  
  4963.  Then, assign it without using the ampersand, as follows:
  4964.  
  4965.  goodptr = buf;
  4966.  
  4967.  Because the header file setjmp.h defines a jmp_buf as an array of
  4968.  integers, using the ampersand operator generates the warning described
  4969.  above. The reason for choosing an array type rather than a structure
  4970.  has to do with common C coding practices and is described in section
  4971.  4.6 of the Rationale for the ANSI C Standard.
  4972.  
  4973.  Basically, the setjmp() function must change the jmp_buf parameter in
  4974.  order to record where to come back to when longjmp() is executed.
  4975.  Elsewhere, the standard defines setjmp() as taking a single parameter
  4976.  of type jmp_buf, NOT of type "pointer to jmp_buf." The jmp_buf cannot
  4977.  be a structure because structures are passed by value and therefore
  4978.  could not receive changes made by setjmp(). Since arrays are passed by
  4979.  reference (i.e. by their address), setjmp() can change a parameter
  4980.  that is passed as an array.
  4981.  
  4982.  The declaration for badptr (below) declares it to be of type "pointer
  4983.  to array of integer," not "pointer to integer." Doing an assignment
  4984.  with different pointer types gives the C4047 warning error. (In order
  4985.  to do the assignment without a warning, badptr would have to be
  4986.  "pointer to integer" because that's the compatible pointer type for
  4987.  "array of integer.")
  4988.  
  4989.  Instead, using goodptr, declared "pointer to void," allows the
  4990.  assignment to be made without generating a warning. This is also
  4991.  portable code. Note that you cannot use indirection (or subscripting,
  4992.  which is a form of indirection) on void pointers.
  4993.  
  4994.  However, because you don't know what's in the jump buffer anyway, this
  4995.  should be no problem. (The contents of the jump buffer are
  4996.  implementation-dependent and could even differ from version to version
  4997.  of the same compiler. Any code that directly manipulates jump buffers
  4998.  is also implementation-dependent and non-portable.)
  4999.  
  5000.  A brief example program follows:
  5001.  
  5002.  #include <stdio.h>
  5003.  #include <setjmp.h>
  5004.  
  5005.  jmp_buf buf;
  5006.  jmp_buf *badptr;
  5007.  void *goodptr;
  5008.  
  5009.  main()
  5010.  {
  5011.      badptr = &buf;
  5012.          /*  warning C4046: '&' on function/array, ignored        */
  5013.          /*  warning C4047: '=' : different levels of indirection */
  5014.  
  5015.      badptr = buf;
  5016.          /*  warning C4047: '=' : different levels of indirection  */
  5017.  
  5018.      goodptr = buf;
  5019.          /*    this works and is the proper way to do this!!!      */
  5020.  
  5021.      exit(0);
  5022.  }
  5023.  
  5024.  
  5025.  119. Corrections to the _setbkcolor Example
  5026.  
  5027.  Product Version(s): 5.00 5.10 | 5.10
  5028.  Operating System:   MS-DOS    | OS/2
  5029.  Flags: ENDUSER | docerr
  5030.  Last Modified: 12-OCT-1988    ArticleIdent: Q34923
  5031.  
  5032.  Problem:
  5033.  
  5034.  The example program on Page 515 of the "Microsoft C 5.0 (and 5.1)
  5035.  Optimizing Compiler Run-Time Library Reference" and the "Microsoft
  5036.  QuickC Run-Time Library Reference" is supposed to run through 20
  5037.  different background colors, displaying the use of _setbkcolor. When I
  5038.  try to run the program, my screen flickers and I am returned to the
  5039.  DOS prompt.
  5040.  
  5041.  Response:
  5042.  
  5043.  The example is incorrect. The following example changes the background
  5044.  color in graphics mode (this example can be found on the Libraries 1
  5045.  disk of the QuickC Version 1.01 compiler, in PROGRAMS\SBKCOL.C):
  5046.  
  5047.  #include <stdio.h>
  5048.  #include <graph.h>
  5049.  
  5050.  long color[16] = {_BLACK,_BLUE,_GREEN,_CYAN,_RED,_MAGENTA,
  5051.       _BROWN,_WHITE,_GRAY,_LIGHTBLUE,_LIGHTGREEN,_LIGHTCYAN,
  5052.       _LIGHTRED,_LIGHTMAGENTA,_LIGHTYELLOW,_BRIGHTWHITE};
  5053.  
  5054.  main()
  5055.  {
  5056.   int loop;
  5057.   long i;
  5058.   _setvideomode(_HRES16COLOR);
  5059.   for (loop = 0; loop < 16; loop++ ) {
  5060.   _setbkcolor(color[loop]);
  5061.   for (i=0; i < 50000; i++)     /* null loop */
  5062.      ;
  5063.   _setvideomode (_DEFAULTMODE);
  5064.  }
  5065.  
  5066.  The next example changes the background color in text mode:
  5067.  
  5068.  #include <stdio.h>
  5069.  #include <graph.h>
  5070.  
  5071.  main()
  5072.  {
  5073.    long loop;
  5074.    for (loop = 0; loop < 16; loop++)
  5075.      {
  5076.        _setbkcolor(loop);
  5077.        _outtext("    hello    \n");
  5078.      }
  5079.  }
  5080.  
  5081.  
  5082.  120. Errors R6012 to R6015 Documented in QuickC 1.01 Guide
  5083.  
  5084.  Product Version(s): 5.00 5.10 | 5.10
  5085.  Operating System:   MS-DOS    | OS/2
  5086.  Flags: ENDUSER | docerr
  5087.  Last Modified: 14-MAR-1990    ArticleIdent: Q34988
  5088.  
  5089.  The C Run-Time error messages below are not included in
  5090.  "Appendix E -- Error Messages" in the "Microsoft C Optimizing Compiler
  5091.  User's Guide"; nor are they located in ERRMSG.DOC. They are documented
  5092.  in the "Microsoft QuickC Compiler Programmer's Guide" on Page 363, as
  5093.  follows:
  5094.  
  5095.  R6012 invalid near pointer reference
  5096.  R6013 invalid far pointer reference
  5097.  R6014 control-BREAK encountered
  5098.  R6015 unexpected interrupt
  5099.  
  5100.  According to the README.DOC found on the Product Disk for QuickC
  5101.  Version 1.00 and on the Setup Disk for QuickC Version 1.01, the
  5102.  run-time error messages R6012 and R6013 have changed as follows:
  5103.  
  5104.  1. R6012 illegal near pointer use
  5105.  
  5106.     A null near pointer was used in the program.
  5107.  
  5108.     This error only occurs if pointer checking is in effect (i.e.,
  5109.     if the program was compiled in the QuickC environment
  5110.     with the Pointer Check option in the Compile dialog box, the
  5111.     /Zr option on the QCL command line, or the pointer_check
  5112.     pragma in effect).
  5113.  
  5114.  2. R6013 illegal far pointer use
  5115.  
  5116.     An out-of-range far pointer was used in the program.
  5117.  
  5118.     This error only occurs if pointer checking is in effect (i.e. if
  5119.     the program was compiled in the QuickC environment with the
  5120.     Pointer Check option in the Compile dialog box, the /Zr option
  5121.     on the QCL command line, or the pointer_check pragma in effect).
  5122.  
  5123.  In addition, the following new error messages are documented:
  5124.  
  5125.  1. R6014 control-BREAK encountered
  5126.  
  5127.     You pressed CTRL+BREAK to stop the execution of a program within
  5128.     the QuickC environment.
  5129.  
  5130.  2. R6015 unexpected interrupt
  5131.  
  5132.     The program could not be run because it contained unexpected
  5133.     interrupts.
  5134.  
  5135.  When you create an in-memory program from a program list, QuickC
  5136.  automatically creates object files and passes them to the linker. If
  5137.  you compile with the Debug option turned on, the object files that
  5138.  QuickC passes to the linker contain interrupts that are required
  5139.  within the QuickC environment. However, you cannot run a program
  5140.  created from such object files outside of the QuickC programming
  5141.  environment.
  5142.  
  5143.  
  5144.  121. Unresolved Externals when Linking for Protected Mode
  5145.  
  5146.  Product Version(s): 5.10   | 5.10
  5147.  Operating System:   MS-DOS | OS/2
  5148.  Flags: ENDUSER |
  5149.  Last Modified: 12-OCT-1988    ArticleIdent: Q35031
  5150.  
  5151.  Problem:
  5152.  
  5153.  I am compiling my C program for protected-mode with the command:
  5154.  
  5155.  cl /Lp demo.c
  5156.  
  5157.  I'm using the Microsoft Segmented-Executable Linker Version
  5158.  5.01.04, but at link-time I get about 10 unresolved externals,
  5159.  all of which are OS/2 API calls such as DOSWRITE, DOSCLOSE,
  5160.  DOSEXIT.
  5161.  
  5162.  If I link in the library DOSCALLS.LIB, as follows, the problem is
  5163.  corrected:
  5164.  
  5165.  cl /Lp demo.c doscalls.lib
  5166.  
  5167.  The manual does not state that DOSCALLS.LIB must be explicitly linked.
  5168.  
  5169.  Response:
  5170.  
  5171.  This problem occurs because you are using the wrong version of the
  5172.  Microsoft Segmented-Executable Linker. You should be using Version
  5173.  5.01.21, which was distributed with C Version 5.10. Version 5.01.04 is
  5174.  the OS/2 linker.
  5175.  
  5176.  You must link in DOSCALLS.LIB with Version 5.01.04 because this
  5177.  version of LINK does not have the ability to bring in libraries that
  5178.  are themselves requested by a library.
  5179.  
  5180.  The library xLIBCyP.LIB (where x is the memory model and y is the math
  5181.  package) contains a request for DOSCALLS.LIB. Link Version 5.01.21
  5182.  understands this request and searches for DOSCALLS.LIB in the
  5183.  directories specified in the LIB environment variable; LINK Version
  5184.  5.01.04 does not understand this request.
  5185.  
  5186.  
  5187.  122. Don't Place Communal Data in Libraries
  5188.  
  5189.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  5190.  Operating System:   MS-DOS              | OS/2
  5191.  Flags: ENDUSER | S_LIB S_LINK  lib link
  5192.  Last Modified:  8-SEP-1988    ArticleIdent: Q35032
  5193.  
  5194.  Do not declare unitialized (communal) data in modules that will
  5195.  be placed in libraries. Doing so may result in the module not
  5196.  being included at link time.
  5197.  
  5198.  This information is documented in the last paragraph on Page 84 of the
  5199.  "Microsoft C Language Reference" manual, which states the following:
  5200.  
  5201.  "Unitialized variable declarations at the external level are
  5202.  not recommended for any file that might be placed in a library."
  5203.  
  5204.  Microsoft C supports four different storage classes for variables
  5205.  declared at the external level, as follows:
  5206.  
  5207.  1.  Static variables are local to the module and do not generate
  5208.      external references or public definitions, i.e., no other modules
  5209.      may reference these variables.
  5210.  
  5211.  2.  Initialized variables, without static, are allocated storage
  5212.      and generate public definitions, i.e., other modules may share
  5213.      these variables.
  5214.  
  5215.  3.  Uninitialized variables, with extern, are not allocated
  5216.      storage and they generate external references, i.e, this module
  5217.      isn't declaring the data, but it wants to share the data that other
  5218.      modules declare.
  5219.  
  5220.  4.  Communal variables are global variables that are not initialized
  5221.      or given the extern modifier. A communal variable is one that is
  5222.      used by everybody but not necessarily declared public by anybody;
  5223.      the linker will allocate storage for it, if needed.
  5224.  
  5225.      Communal variables do not have external references or public
  5226.      definitions. When the program is linked, if a public definition
  5227.      with the same name is found, all communal declarations are treated
  5228.      as external references. If no definition is found, the linker will
  5229.      allocate storage and again the communal declarations are treated
  5230.      like references. When a module is added to a library, the librarian
  5231.      takes all public definitions and adds them to the dictionary to be
  5232.      searched when the linker resolves references to the library.
  5233.  
  5234.  Note: Communal variables are NOT added to the dictionary. To do so
  5235.  would cause conflicts with other communal declarations and a possible
  5236.  public definition.
  5237.  
  5238.  A good way to declare data in a multi-module program is to use a
  5239.  single module that contains public definitions while every other
  5240.  module uses the extern modifier. You do not need to actually
  5241.  initialize all variables in this one module as long as one of them is
  5242.  initialized. This process is sufficient to force the module to be
  5243.  brought in while linking.
  5244.  
  5245.  
  5246.  123. How C Interprets Integer Constants with Leading Zeroes
  5247.  
  5248.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  5249.  Operating System:   MS-DOS              | OS/2
  5250.  Flags: ENDUSER |
  5251.  Last Modified: 18-OCT-1988    ArticleIdent: Q35037
  5252.  
  5253.  Question:
  5254.  
  5255.  Why do the assignments "a = 20" and "a = 020" return different results
  5256.  when the values are printed? Why aren't 020 and 20 the same?
  5257.  
  5258.  The following is an example:
  5259.  
  5260.  a = 20;
  5261.  printf("%d", a);   /* this prints "20" */
  5262.  a = 020;
  5263.  printf("%d", a);   /* but this prints "16" */
  5264.  
  5265.  Response:
  5266.  
  5267.  In C, any number preceded by a 0 is handled as an octal number (base
  5268.  8). Therefore, "a = 20" is handled as you would expect; however, "a =
  5269.  020" is handled as an octal number and therefore represents the
  5270.  decimal value 16.
  5271.  
  5272.  Note also that ALL character constants of the form '\o', '\oo',
  5273.  '\ooo', and the string equivalents are always octal as well.  (Hex
  5274.  character constants start with "\x".)  For instance, '\33' or '\033'
  5275.  are both the ESCape character (decimal 27, hex 1B).  There is no way
  5276.  to use decimal numbers to specify a character constant; however, you
  5277.  may use decimal integer constants instead (example: ch = 27;  ).
  5278.  
  5279.  
  5280.  124. Weitek WTL 1167 Math Coprocessor Support
  5281.  
  5282.  Product Version(s): 5.x    | 5.10
  5283.  Operating System:   MS-DOS | OS/2
  5284.  Flags: ENDUSER |
  5285.  Last Modified: 12-OCT-1988    ArticleIdent: Q35142
  5286.  
  5287.  The Weitek WTL 1167 is found on Compaq's Weitek Coprocessor Board. The
  5288.  WTL 1167 is a set of three chips used as a replacement for the Intel
  5289.  80387. Benchmarks in the 1988 March BYTE, show the WTL 1167 with a 7
  5290.  percent to 68 percent speed increase over the 80387 on processing of
  5291.  double-precision numbers. ("Real-World" speed increase is more like 30
  5292.  percent.) Compaq's Weitek Coprocessor Board was designed with an 80387
  5293.  socket.
  5294.  
  5295.  Microsoft only has Math Coprocessor support for Intel chips. If you
  5296.  have the WTL 1167 on a Compaq Weitek Coprocessor Board, you also must
  5297.  have an 80387 to use our Math Coprocessor Library. Without the 80387
  5298.  you will have to use our Emulator or Alternate Math Libraries, or link
  5299.  with a third-party library.
  5300.  
  5301.  
  5302.  
  5303.  125. Monochrome Display Adapter Normal Text Example
  5304.  
  5305.  Product Version(s): 5.00 5.10
  5306.  Operating System:   MS-DOS
  5307.  Flags: ENDUSER |
  5308.  Last Modified: 12-OCT-1988    ArticleIdent: Q35285
  5309.  
  5310.  On a monochrome display adapter, there is no way to display colors.
  5311.  However, you can display Normal Text, Bright Text, Reverse Video,
  5312.  Underline, and Blinking.
  5313.  
  5314.  The following program shows how to get Normal Text, No Blinking, No
  5315.  Underlining, and No Inverse on a monochrome display adapter:
  5316.  
  5317.  #include<graph.h>
  5318.  int     oldcolor;
  5319.  long    oldbkcolor;
  5320.  
  5321.  main()
  5322.  {
  5323.   _clearscreen(_GCLEARSCREEN);
  5324.   oldcolor=_gettextcolor();
  5325.   oldbkcolor=_getbkcolor();
  5326.   _settextposition(12,0);
  5327.   _settextcolor(2);            /* foreground color Green */
  5328.   _setbkcolor(0L);             /* background color Black */
  5329.   _outtext("Normal Text, on Mono\n");
  5330.   _settextcolor(oldcolor);
  5331.   _setbkcolor(oldbkcolor);
  5332.  }
  5333.  
  5334.  
  5335.  126. MDA Bright Underlined Text Example
  5336.  
  5337.  Product Version(s): 5.00 5.10
  5338.  Operating System:   MS-DOS
  5339.  Flags: ENDUSER |
  5340.  Last Modified: 12-OCT-1988    ArticleIdent: Q35286
  5341.  
  5342.  On a monochrome display adapter, there is no way to display colors.
  5343.  However, you can display Normal Text, Bright Text, Reverse Video,
  5344.  Underline, and Blinking.
  5345.  
  5346.  The following program shows how to get Bright Text, No Blinking,
  5347.  Underlined, and No Inverse on a monochrome display adapter:
  5348.  
  5349.  #include<graph.h>
  5350.  int     oldcolor;
  5351.  long    oldbkcolor;
  5352.  
  5353.  main()
  5354.  {
  5355.   _clearscreen(_GCLEARSCREEN);
  5356.   oldcolor=_gettextcolor();
  5357.   oldbkcolor=_getbkcolor();
  5358.   _settextposition(12,0);
  5359.   _settextcolor(9);            /* foreground color Intence Blue */
  5360.   _setbkcolor(0L);             /* background color Black */
  5361.   _outtext("Bright Underlined Text, on Mono\n");
  5362.   _settextcolor(oldcolor);
  5363.   _setbkcolor(oldbkcolor);
  5364.  }
  5365.  
  5366.  
  5367.  127. MDA Normal Inverse Text Example
  5368.  
  5369.  Product Version(s): 5.00 5.10
  5370.  Operating System:   MS-DOS
  5371.  Flags: ENDUSER |
  5372.  Last Modified: 12-OCT-1988    ArticleIdent: Q35287
  5373.  
  5374.  On a monochrome display adapter, there is no way to display colors.
  5375.  However, you can display Normal Text, Bright Text, Reverse Video,
  5376.  Underline, and Blinking.
  5377.  
  5378.  The following program shows how to get Normal Text, No Blinking, No
  5379.  Underlining, and Inverse on a monochrome display adapter:
  5380.  
  5381.  #include<graph.h>
  5382.  int     oldcolor;
  5383.  long    oldbkcolor;
  5384.  
  5385.  main()
  5386.  {
  5387.   _clearscreen(_GCLEARSCREEN);
  5388.   oldcolor=_gettextcolor();
  5389.   oldbkcolor=_getbkcolor();
  5390.   _settextposition(12,0);
  5391.   _settextcolor(0);            /* foreground color Black */
  5392.   _setbkcolor(7L);             /* background color White */
  5393.   _outtext("Normal Inverse Text, on Mono\n");
  5394.   _settextcolor(oldcolor);
  5395.   _setbkcolor(oldbkcolor);
  5396.  }
  5397.  
  5398.  
  5399.  128. MDA Blinking Normal Text Example
  5400.  
  5401.  Product Version(s): 5.00 5.10
  5402.  Operating System:   MS-DOS
  5403.  Flags: ENDUSER |
  5404.  Last Modified: 27-OCT-1988    ArticleIdent: Q35288
  5405.  
  5406.  On a monochrome display adapter, there is no way to display colors.
  5407.  However, you can display Normal Text, Bright Text, Reverse Video,
  5408.  Underline, and Blinking.
  5409.  
  5410.  The following program shows how to get Normal Text, Blinking, No
  5411.  Underlining, and No Inverse on a monochrome display adapter:
  5412.  
  5413.  #include<graph.h>
  5414.  int     oldcolor;
  5415.  long    oldbkcolor;
  5416.  
  5417.  main()
  5418.  {
  5419.   _clearscreen(_GCLEARSCREEN);
  5420.   oldcolor=_gettextcolor();
  5421.   oldbkcolor=_getbkcolor();
  5422.   _settextposition(12,0);
  5423.   _settextcolor(18);           /* foreground color Green + 16 */
  5424.   _setbkcolor(0L);             /* background color Black */
  5425.   _outtext("Blinking Normal Text, on Mono\n");
  5426.   _settextcolor(oldcolor);
  5427.   _setbkcolor(oldbkcolor);
  5428.  }
  5429.  
  5430.  
  5431.  129. MDA Blinking Bright Text Example
  5432.  
  5433.  Product Version(s): 5.00 5.10
  5434.  Operating System:   MS-DOS
  5435.  Flags: ENDUSER |
  5436.  Last Modified: 12-OCT-1988    ArticleIdent: Q35289
  5437.  
  5438.  On a monochrome display adapter, there is no way to display colors.
  5439.  However, you can display Normal Text, Bright Text, Reverse Video,
  5440.  Underline, and Blinking.
  5441.  
  5442.  The following program shows how to get Bright Text, Blinking, No
  5443.  Underlining, and No Inverse on a monochrome display adapter:
  5444.  
  5445.  #include<graph.h>
  5446.  int     oldcolor;
  5447.  long    oldbkcolor;
  5448.  
  5449.  main()
  5450.  {
  5451.   _clearscreen(_GCLEARSCREEN);
  5452.   oldcolor=_gettextcolor();
  5453.   oldbkcolor=_getbkcolor();
  5454.   _settextposition(12,0);
  5455.   _settextcolor(26);       /* foreground color Intense Green + 16 */
  5456.   _setbkcolor(0L);         /* background color Black */
  5457.   _outtext("Blinking Bright Text, on Mono\n");
  5458.   _settextcolor(oldcolor);
  5459.   _setbkcolor(oldbkcolor);
  5460.  }
  5461.  
  5462.  
  5463.  130. MDA Blinking Normal Underlined Text Example
  5464.  
  5465.  Product Version(s): 5.00 5.10
  5466.  Operating System:   MS-DOS
  5467.  Flags: ENDUSER |
  5468.  Last Modified: 12-OCT-1988    ArticleIdent: Q35290
  5469.  
  5470.  On a monochrome display adapter, there is no way to display colors.
  5471.  However, you can display Normal Text, Bright Text, Reverse Video,
  5472.  Underline, and Blinking.
  5473.  
  5474.  The following program shows how to get Normal Text, Blinking,
  5475.  Underlined, and No Inverse on a monochrome display adapter:
  5476.  
  5477.  #include<graph.h>
  5478.  int     oldcolor;
  5479.  long    oldbkcolor;
  5480.  
  5481.  main()
  5482.  {
  5483.   _clearscreen(_GCLEARSCREEN);
  5484.   oldcolor=_gettextcolor();
  5485.   oldbkcolor=_getbkcolor();
  5486.   _settextposition(12,0);
  5487.   _settextcolor(17);           /* foreground color Blue + 16 */
  5488.   _setbkcolor(0L);             /* background color Black */
  5489.   _outtext("Blinking Normal Underlined Text, on Mono\n");
  5490.   _settextcolor(oldcolor);
  5491.   _setbkcolor(oldbkcolor);
  5492.  }
  5493.  
  5494.  
  5495.  131. MDA Blinking Bright Underlined Text Example
  5496.  
  5497.  Product Version(s): 5.00 5.10
  5498.  Operating System:   MS-DOS
  5499.  Flags: ENDUSER |
  5500.  Last Modified: 12-OCT-1988    ArticleIdent: Q35291
  5501.  
  5502.  On a monochrome display adapter, there is no way to display colors.
  5503.  However, you can display Normal Text, Bright Text, Reverse Video,
  5504.  Underline, and Blinking.
  5505.  
  5506.  The following program shows how to get Bright Text, Blinking,
  5507.  Underlined, and No Inverse on a monochrome display adapter:
  5508.  
  5509.  #include<graph.h>
  5510.  int     oldcolor;
  5511.  long    oldbkcolor;
  5512.  
  5513.  main()
  5514.  {
  5515.   _clearscreen(_GCLEARSCREEN);
  5516.   oldcolor=_gettextcolor();
  5517.   oldbkcolor=_getbkcolor();
  5518.   _settextposition(12,0);
  5519.   _settextcolor(25);           /* foreground color Intence Blue + 16 */
  5520.   _setbkcolor(0L);             /* background color Black */
  5521.   _outtext("Blinking Bright Underlined Text, on Mono\n");
  5522.   _settextcolor(oldcolor);
  5523.   _setbkcolor(oldbkcolor);
  5524.  }
  5525.  
  5526.  
  5527.  132. MDA Blinking Normal Inverse Text Example
  5528.  
  5529.  Product Version(s): 5.00 5.10
  5530.  Operating System:   MS-DOS
  5531.  Flags: ENDUSER |
  5532.  Last Modified: 12-OCT-1988    ArticleIdent: Q35292
  5533.  
  5534.  On a monochrome display adapter, there is no way to display colors.
  5535.  However, you can display Normal Text, Bright Text, Reverse Video,
  5536.  Underline, and Blinking.
  5537.  
  5538.  The following program shows how to get Normal Text, Blinking, No
  5539.  Underlining, and Inverse, on a monochrome display adapter:
  5540.  
  5541.  #include<graph.h>
  5542.  int     oldcolor;
  5543.  long    oldbkcolor;
  5544.  
  5545.  main()
  5546.  {
  5547.   _clearscreen(_GCLEARSCREEN);
  5548.   oldcolor=_gettextcolor();
  5549.   oldbkcolor=_getbkcolor();
  5550.   _settextposition(12,0);
  5551.   _settextcolor(16);            /* foreground color Black + 16 */
  5552.   _setbkcolor(7L);             /* background color White */
  5553.   _outtext("Blinking Normal Inverse Text, on Mono\n");
  5554.   _settextcolor(oldcolor);
  5555.   _setbkcolor(oldbkcolor);
  5556.  }
  5557.  
  5558.  
  5559.  133. Directory Listing of C 5.10 for OS/2 Distribution Disks
  5560.  
  5561.  Product Version(s): 5.10   | 5.10
  5562.  Operating System:   MS-DOS | OS/2
  5563.  Flags: ENDUSER |
  5564.  Last Modified: 12-OCT-1988    ArticleIdent: Q35293
  5565.  
  5566.  Below is a listing of the directories for each of the Microsoft C
  5567.  Version 5.10 Optimizing Compiler distribution disks for the OS/2 and
  5568.  DOS dual mode (5.25-inch disks). The information is the resulting
  5569.  output when the DOS command "dir" is performed on each directory and
  5570.  subdirectory.
  5571.  
  5572.  A line of colons (:::::) separates each disk; subdirectories are
  5573.  listed below their parent directory. The first line of each disk
  5574.  description is the name of the disk as it is printed on the label.
  5575.  Information in parentheses is supplemental and not contained on the
  5576.  disk label.
  5577.  
  5578.  The following is a listing of directories for C Version 5.10
  5579.  distribution disks:
  5580.  
  5581.  (Disk 1 of 14)  -  Setup
  5582.  
  5583.   Volume in drive A has no label
  5584.   Directory of  A:\
  5585.  
  5586.  README   DOC    63360   3-07-88   5:10a
  5587.  UTILITY  DOC    17794   3-07-88   5:10a
  5588.  PACKING  LST    11814   3-07-88   5:10a
  5589.  CL       EXE    31329   3-07-88   5:10a
  5590.  CL       HLP     2169   3-07-88   5:10a
  5591.  CL       ERR     2276   3-07-88   5:10a
  5592.  C1       EXE   114521   3-07-88   5:10a
  5593.  C23      ERR     3272   3-07-88   5:10a
  5594.  SETUP    EXE    93033   3-07-88   5:10a
  5595.  SETUP    DOC    15179   3-07-88   5:10a
  5596.         10 File(s)      3072 bytes free
  5597.  
  5598.  :::::::::::::::::::::::::::::::::::::::
  5599.  
  5600.  (Disk 2 of 14)  -  Include Files and Startup Source Code
  5601.  
  5602.   Volume in drive A has no label
  5603.   Directory of  A:\
  5604.  
  5605.  STARTUP      <DIR>      3-07-88   5:10a
  5606.  INCLUDE      <DIR>      3-07-88   5:10a
  5607.          2 File(s)     29696 bytes free
  5608.  
  5609.   Volume in drive A has no label
  5610.   Directory of  A:\INCLUDE
  5611.  
  5612.  .            <DIR>      3-07-88   5:10a
  5613.  ..           <DIR>      3-07-88   5:10a
  5614.  SYS          <DIR>      3-07-88   5:10a
  5615.  ASSERT   H        699   3-07-88   5:10a
  5616.  BIOS     H       4866   3-07-88   5:10a
  5617.  CONIO    H        952   3-07-88   5:10a
  5618.  CTYPE    H       2465   3-07-88   5:10a
  5619.  DIRECT   H        690   3-07-88   5:10a
  5620.  DOS      H       5917   3-07-88   5:10a
  5621.  ERRNO    H       1283   3-07-88   5:10a
  5622.  FCNTL    H       1255   3-07-88   5:10a
  5623.  FLOAT    H       6011   3-07-88   5:10a
  5624.  GRAPH    H       7480   3-07-88   5:10a
  5625.  IO       H       1294   3-07-88   5:10a
  5626.  LIMITS   H       1553   3-07-88   5:10a
  5627.  MALLOC   H       3097   3-07-88   5:10a
  5628.  MATH     H       3324   3-07-88   5:10a
  5629.  MEMORY   H       1065   3-07-88   5:10a
  5630.  SEARCH   H       1025   3-07-88   5:10a
  5631.  SETJMP   H        907   3-07-88   5:10a
  5632.  SHARE    H        554   3-07-88   5:10a
  5633.  SIGNAL   H       1905   3-07-88   5:10a
  5634.  STDARG   H        614   3-07-88   5:10a
  5635.  STDDEF   H       1100   3-07-88   5:10a
  5636.  STDIO    H       4500   3-07-88   5:10a
  5637.  STDLIB   H       4900   3-07-88   5:10a
  5638.  STRING   H       2209   3-07-88   5:10a
  5639.  TIME     H       2342   3-07-88   5:10a
  5640.  VARARGS  H        642   3-07-88   5:10a
  5641.  PROCESS  H       1988   3-07-88   5:10a
  5642.  OS2      H        707   3-07-88   5:10a
  5643.  OS2DEF   H       5891   3-07-88   5:10a
  5644.  BSE      H       1139   3-07-88   5:10a
  5645.  BSEDOS   H      17730   3-07-88   5:10a
  5646.  BSEERR   H      20940   3-07-88   5:10a
  5647.  BSESUB   H      11512   3-07-88   5:10a
  5648.         36 File(s)     29696 bytes free
  5649.  
  5650.   Volume in drive A has no label
  5651.   Directory of  A:\INCLUDE\SYS
  5652.  
  5653.  .            <DIR>      3-07-88   5:10a
  5654.  ..           <DIR>      3-07-88   5:10a
  5655.  LOCKING  H        573   3-07-88   5:10a
  5656.  STAT     H       1497   3-07-88   5:10a
  5657.  TIMEB    H        844   3-07-88   5:10a
  5658.  TYPES    H        849   3-07-88   5:10a
  5659.  UTIME    H       1061   3-07-88   5:10a
  5660.          7 File(s)     29696 bytes free
  5661.  
  5662.   Volume in drive A has no label
  5663.   Directory of  A:\STARTUP
  5664.  
  5665.  .            <DIR>      3-07-88   5:10a
  5666.  ..           <DIR>      3-07-88   5:10a
  5667.  DOS          <DIR>      3-07-88   5:10a
  5668.  OS2          <DIR>      3-07-88   5:10a
  5669.  FILE2    H       1027   3-07-88   5:10a
  5670.  MSDOS    H       6849   3-07-88   5:10a
  5671.  REGISTER H        922   3-07-88   5:10a
  5672.  STARTUP  BAT     1663   3-07-88   5:10a
  5673.  MAKEFILE         4148   3-07-88   5:10a
  5674.  CHKSTK   ASM     2044   3-07-88   5:10a
  5675.  CHKSUM   ASM     3524   3-07-88   5:10a
  5676.  NULBODY  C         13   3-07-88   5:10a
  5677.  README   DOC     3199   3-07-88   5:10a
  5678.  MSDOS    INC     6181   3-07-88   5:10a
  5679.  CMACROS  INC    12066   3-07-88   5:10a
  5680.  BRKCTL   INC      784   3-07-88   5:10a
  5681.  VERSION  INC      503   3-07-88   5:10a
  5682.  WILD     C       7182   3-07-88   5:10a
  5683.  _FILE    C       1691   3-07-88   5:10a
  5684.  CRT0FP   ASM     2223   3-07-88   5:10a
  5685.  FMSGHDR  ASM     2429   3-07-88   5:10a
  5686.  SETARGV  ASM      971   3-07-88   5:10a
  5687.         22 File(s)     29696 bytes free
  5688.  
  5689.   Volume in drive A has no label
  5690.   Directory of  A:\STARTUP\DOS
  5691.  
  5692.  .            <DIR>      3-07-88   5:10a
  5693.  ..           <DIR>      3-07-88   5:10a
  5694.  NULBODY  LNK      149   3-07-88   5:10a
  5695.  STDENVP  ASM     3780   3-07-88   5:10a
  5696.  CRT0     ASM     7612   3-07-88   5:10a
  5697.  CRT0DAT  ASM    14175   3-07-88   5:10a
  5698.  CRT0MSG  ASM     2840   3-07-88   5:10a
  5699.  EXECMSG  ASM     1337   3-07-88   5:10a
  5700.  NMSGHDR  ASM     3010   3-07-88   5:10a
  5701.  STDALLOC ASM     2825   3-07-88   5:10a
  5702.  STDARGV  ASM    13852   3-07-88   5:10a
  5703.         11 File(s)     29696 bytes free
  5704.  
  5705.   Volume in drive A has no label
  5706.   Directory of  A:\STARTUP\OS2
  5707.  
  5708.  .            <DIR>      3-07-88   5:10a
  5709.  ..           <DIR>      3-07-88   5:10a
  5710.  NULBODY  LNK      168   3-07-88   5:10a
  5711.  CRT0     ASM    10312   3-07-88   5:10a
  5712.  STDENVP  ASM     5362   3-07-88   5:10a
  5713.  CRT0DAT  ASM    10496   3-07-88   5:10a
  5714.  CRT0MSG  ASM     2891   3-07-88   5:10a
  5715.  EXECMSG  ASM     2231   3-07-88   5:10a
  5716.  NMSGHDR  ASM     3486   3-07-88   5:10a
  5717.  STDALLOC ASM     3245   3-07-88   5:10a
  5718.  STDARGV  ASM    13623   3-07-88   5:10a
  5719.         11 File(s)     29696 bytes free
  5720.  
  5721.  :::::::::::::::::::::::::::::::::::::::
  5722.  
  5723.  (Disk 3 of 14)  -  Compiler 1
  5724.  
  5725.   Volume in drive A has no label
  5726.   Directory of  A:\
  5727.  
  5728.  PATCH        <DIR>      3-07-88   5:10a
  5729.  C1       ERR    14393   3-07-88   5:10a
  5730.  C1L      EXE   149303   3-07-88   5:10a
  5731.  C3       EXE   125221   3-07-88   5:10a
  5732.  ERRMSG   DOC    17293   3-07-88   5:10a
  5733.  FPEXCEPT DOC    16254   3-07-88   5:10a
  5734.          6 File(s)     15360 bytes free
  5735.  
  5736.   Volume in drive A has no label
  5737.   Directory of  A:\PATCH
  5738.  
  5739.  .            <DIR>      3-07-88   5:10a
  5740.  ..           <DIR>      3-07-88   5:10a
  5741.  PATCH87  DOC     3937   3-07-88   5:10a
  5742.  PATCH87  EXE     4206   3-07-88   5:10a
  5743.  SETRHS   EXE      543   3-07-88   5:10a
  5744.  RMRHS    EXE      543   3-07-88   5:10a
  5745.  STKPAT   BAT       94   3-07-88   5:10a
  5746.  STKPAT   SCR       30   3-07-88   5:10a
  5747.  PTRACE87 PAT      188   3-07-88   5:10a
  5748.  PATCH320 DOC     2169   3-07-88   5:10a
  5749.  OS2PATCH EXE     1069   3-07-88   5:10a
  5750.  OS2PATCH DOC     1401   3-07-88   5:10a
  5751.         12 File(s)     15360 bytes free
  5752.  
  5753.  :::::::::::::::::::::::::::::::::::::::
  5754.  
  5755.  (Disk 4 of 14)  -  Compiler 2
  5756.  
  5757.   Volume in drive A has no label
  5758.   Directory of  A:\
  5759.  
  5760.  FIXSHIFT COM      688   3-07-88   5:10a
  5761.  MSHERC   COM     6749   3-07-88   5:10a
  5762.  QLIB     DOC    12047   3-07-88   5:10a
  5763.  QLIB     EXE    24557   3-07-88   5:10a
  5764.  QLIB     INI     2905   3-07-88   5:10a
  5765.  C2       EXE   202919   3-07-88   5:10a
  5766.  QC       HLP    50649   3-07-88   5:10a
  5767.  SETENV   EXE    10870   3-07-88   5:10a
  5768.  MTDYNA   DOC    43542   3-07-88   5:10a
  5769.          9 File(s)      4096 bytes free
  5770.  
  5771.  :::::::::::::::::::::::::::::::::::::::
  5772.  
  5773.  (Disk 5 of 14)  -  Utilities 1
  5774.  
  5775.   Volume in drive A has no label
  5776.   Directory of  A:\
  5777.  
  5778.  ERROUT   EXE    10729   3-07-88   5:10a
  5779.  EXEHDR   EXE    29942   3-07-88   5:10a
  5780.  EXEMOD   EXE    12336   3-07-88   5:10a
  5781.  EXEPACK  EXE    14803   3-07-88   5:10a
  5782.  IMPLIB   EXE    30166   3-07-88   5:10a
  5783.  LIB      EXE    49661   3-07-88   5:10a
  5784.  LINK     EXE   117001   3-07-88   5:10a
  5785.  MAKE     EXE    38613   3-07-88   5:10a
  5786.  MOUSE    COM    14545   3-07-88   5:10a
  5787.  README   QC     30360   3-07-88   5:10a
  5788.         10 File(s)      8192 bytes free
  5789.  
  5790.  :::::::::::::::::::::::::::::::::::::::
  5791.  
  5792.  (Disk 6 of 14)  -  Utilities 2
  5793.  
  5794.   Volume in drive A has no label
  5795.   Directory of  A:\
  5796.  
  5797.  EXT          <DIR>      3-07-88   5:10a
  5798.  INI          <DIR>      3-07-88   5:10a
  5799.  BIND     EXE    36946   3-07-88   5:10a
  5800.  CALLTREE EXE    31233   3-07-88   5:10a
  5801.  ECH      EXE    19351   3-07-88   5:10a
  5802.  EXP      EXE    32220   3-07-88   5:10a
  5803.  M        EXE    94821   3-07-88   5:10a
  5804.  MEGREP   EXE    31915   3-07-88   5:10a
  5805.  RM       EXE    24884   3-07-88   5:10a
  5806.  UNDEL    EXE    30046   3-07-88   5:10a
  5807.         10 File(s)      8192 bytes free
  5808.  
  5809.   Volume in drive A has no label
  5810.   Directory of  A:\EXT
  5811.  
  5812.  .            <DIR>      3-07-88   5:10a
  5813.  ..           <DIR>      3-07-88   5:10a
  5814.  EXT      DOC    15877   3-07-88   5:10a
  5815.  EXT      H       8730   3-07-88   5:10a
  5816.  EXTHDR   OBJ     1893   3-07-88   5:10a
  5817.  EXTHDRP  OBJ     2021   3-07-88   5:10a
  5818.  SKEL     C       2457   3-07-88   5:10a
  5819.  SKEL     DEF      211   3-07-88   5:10a
  5820.  WS       DLL     2609   3-07-88   5:10a
  5821.  WS       ZXT     2084   3-07-88   5:10a
  5822.         10 File(s)      8192 bytes free
  5823.  
  5824.   Volume in drive A has no label
  5825.   Directory of  A:\INI
  5826.  
  5827.  .            <DIR>      3-07-88   5:10a
  5828.  ..           <DIR>      3-07-88   5:10a
  5829.  BRIEF    INI     2094   3-07-88   5:10a
  5830.  EPSILON  INI      978   3-07-88   5:10a
  5831.  QUICK    INI     1058   3-07-88   5:10a
  5832.          5 File(s)      8192 bytes free
  5833.  
  5834.  :::::::::::::::::::::::::::::::::::::::
  5835.  
  5836.  (Disk 7 of 14)  -  Libraries (Small and Medium Models)
  5837.  
  5838.   Volume in drive A has no label
  5839.   Directory of  A:\
  5840.  
  5841.  SLIBCR   LIB   132047   3-07-88   5:10a
  5842.  SLIBFA   LIB    46089   3-07-88   5:10a
  5843.  SVARSTCK OBJ      507   3-07-88   5:10a
  5844.  MLIBCR   LIB   133071   3-07-88   5:10a
  5845.  MLIBFA   LIB    46601   3-07-88   5:10a
  5846.  MVARSTCK OBJ      507   3-07-88   5:10a
  5847.          6 File(s)      1024 bytes free
  5848.  
  5849.  :::::::::::::::::::::::::::::::::::::::
  5850.  
  5851.  (Disk 8 of 14)  -  Libraries (Large and Compact Models)
  5852.  
  5853.   Volume in drive A has no label
  5854.   Directory of  A:\
  5855.  
  5856.  CLIBCR   LIB   141301   3-07-88   5:10a
  5857.  CVARSTCK OBJ      487   3-07-88   5:10a
  5858.  LLIBCR   LIB   142837   3-07-88   5:10a
  5859.  LLIBFA   LIB    47625   3-07-88   5:10a
  5860.  LVARSTCK OBJ      487   3-07-88   5:10a
  5861.          5 File(s)     27648 bytes free
  5862.  
  5863.  :::::::::::::::::::::::::::::::::::::::
  5864.  
  5865.  (Disk 9 of 14)  -  Floating-Point Libraries
  5866.  
  5867.   Volume in drive A has no label
  5868.   Directory of  A:\
  5869.  
  5870.  FORTRAN      <DIR>      3-07-88   5:10a
  5871.  EM       LIB    16921   3-07-88   5:10a
  5872.  87       LIB     4121   3-07-88   5:10a
  5873.  DOSCALLS LIB    29184   3-07-88   5:10a
  5874.  GRAPHICS LIB    59357   3-07-88   5:10a
  5875.  LIBH     LIB    14209   3-07-88   5:10a
  5876.  QUICKLIB OBJ     7917   3-07-88   5:10a
  5877.  SETARGV  OBJ      143   3-07-88   5:10a
  5878.  BINMODE  OBJ      127   3-07-88   5:10a
  5879.  SLIBFP   LIB    37281   3-07-88   5:10a
  5880.  MLIBFP   LIB    38305   3-07-88   5:10a
  5881.  CLIBFA   LIB    47113   3-07-88   5:10a
  5882.  CLIBFP   LIB    38307   3-07-88   5:10a
  5883.  LLIBFP   LIB    39331   3-07-88   5:10a
  5884.         14 File(s)     15360 bytes free
  5885.  
  5886.   Volume in drive A has no label
  5887.   Directory of  A:\FORTRAN
  5888.  
  5889.  .            <DIR>      3-07-88   5:10a
  5890.  ..           <DIR>      3-07-88   5:10a
  5891.  MDBGMSG  OBJ      540   3-07-88   5:10a
  5892.  LDBGMSG  OBJ      544   3-07-88   5:10a
  5893.  F4COMPAT BAT     3107   3-07-88   5:10a
  5894.          5 File(s)     15360 bytes free
  5895.  
  5896.  :::::::::::::::::::::::::::::::::::::::
  5897.  
  5898.  (Disk 10 of 14)  -  Microsoft QuickC for MS-DOS
  5899.  
  5900.   Volume in drive A has no label
  5901.   Directory of  A:\
  5902.  
  5903.  QC       EXE   326656   3-07-88   5:10a
  5904.  QCL      EXE    28065   3-07-88   5:10a
  5905.  QCL      HLP     1456   3-07-88   5:10a
  5906.          3 File(s)      5120 bytes free
  5907.  
  5908.  :::::::::::::::::::::::::::::::::::::::
  5909.  
  5910.  (Disk 11 of 14)  -  Microsoft CodeView for MS-DOS with Tutorial
  5911.  
  5912.   Volume in drive A has no label
  5913.   Directory of  A:\
  5914.  
  5915.  SAMPLE       <DIR>      3-07-88   5:10a
  5916.  CV       EXE   232896   3-07-88   5:10a
  5917.          2 File(s)      3072 bytes free
  5918.  
  5919.   Volume in drive A has no label
  5920.   Directory of  A:\SAMPLE
  5921.  
  5922.  .            <DIR>      3-07-88   5:10a
  5923.  ..           <DIR>      3-07-88   5:10a
  5924.  CODEVIEW DOC    12928   3-07-88   5:10a
  5925.  ADAPT    BAT      133   3-07-88   5:10a
  5926.  DEMOB    BAT      254   3-07-88   5:10a
  5927.  LIFEB    BAT      336   3-07-88   5:10a
  5928.  LIFEEB   BAT      402   3-07-88   5:10a
  5929.  MENU     BAT      550   3-07-88   5:10a
  5930.  SAMPLE   BAT     1059   3-07-88   5:10a
  5931.  LIFE     C      14713   3-07-88   5:10a
  5932.  LIFE     EXE    33237   3-07-88   5:10a
  5933.  LIFE     R       5282   3-07-88   5:10a
  5934.  C_AUTO   CV      3571   3-07-88   5:10a
  5935.  E_AUTO   CV      6788   3-07-88   5:10a
  5936.  L_AUTO   CV     13272   3-07-88   5:10a
  5937.  M_AUTO   CV       733   3-07-88   5:10a
  5938.  Q_AUTO   CV        15   3-07-88   5:10a
  5939.  S_AUTO   CV      9091   3-07-88   5:10a
  5940.  RESPOND  COM      124   3-07-88   5:10a
  5941.  S1       @@@      230   3-07-88   5:10a
  5942.  S12      @@@      926   3-07-88   5:10a
  5943.  S13      @@@      368   3-07-88   5:10a
  5944.  S14      @@@      520   3-07-88   5:10a
  5945.  S2       @@@      752   3-07-88   5:10a
  5946.  S3       @@@      276   3-07-88   5:10a
  5947.  S4       @@@      354   3-07-88   5:10a
  5948.  S5       @@@      554   3-07-88   5:10a
  5949.  S6       @@@      432   3-07-88   5:10a
  5950.  S7       @@@      427   3-07-88   5:10a
  5951.  S8       @@@      479   3-07-88   5:10a
  5952.  S9       @@@      865   3-07-88   5:10a
  5953.         31 File(s)      3072 bytes free
  5954.  
  5955.  :::::::::::::::::::::::::::::::::::::::
  5956.  
  5957.  (Disk 12 of 14)  -  Utilities 3
  5958.  
  5959.   Volume in drive A has no label
  5960.   Directory of  A:\
  5961.  
  5962.  SOURCE       <DIR>      3-07-88   5:10a
  5963.  ILINK    EXE    88929   3-07-88   5:10a
  5964.  LINK     EXE    65539   3-07-88   5:10a
  5965.  EXEC     EXE     9299   3-07-88   5:10a
  5966.  CV       HLP    21552   3-07-88   5:10a
  5967.  CVPACK   EXE    49400   3-07-88   5:10a
  5968.          6 File(s)     10240 bytes free
  5969.  
  5970.   Volume in drive A has no label
  5971.   Directory of  A:\SOURCE
  5972.  
  5973.  .            <DIR>      3-07-88   5:10a
  5974.  ..           <DIR>      3-07-88   5:10a
  5975.  SAMPLES  DOC     1760   3-07-88   5:10a
  5976.  CFLOW    C      44796   3-07-88   5:10a
  5977.  CFLOW    DOC     3764   3-07-88   5:10a
  5978.  DEMO     C        419   3-07-88   5:10a
  5979.  EMOEM    ASM    12129   3-07-88   5:10a
  5980.  GRDEMO   C      20907   3-07-88   5:10a
  5981.  SIEVE    C        788   3-07-88   5:10a
  5982.  SORTDEMO C      25399   3-07-88   5:10a
  5983.         10 File(s)     10240 bytes free
  5984.  
  5985.  :::::::::::::::::::::::::::::::::::::::
  5986.  
  5987.  (Disk 13 of 14)  -  Microsoft Codeview for MS OS/2
  5988.  
  5989.   Volume in drive A has no label
  5990.   Directory of  A:\
  5991.  
  5992.  INCLMT       <DIR>      3-07-88   5:10a
  5993.  CVP      EXE   222505   3-07-88   5:10a
  5994.  CVP      HLP    21552   3-07-88   5:10a
  5995.  MEP      EXE    97063   3-07-88   5:10a
  5996.  CL       EXE    33900   3-07-88   5:10a
  5997.  CL       ERR     2276   3-07-88   5:10a
  5998.  CL       HLP     2169   3-07-88   5:10a
  5999.  C1       EXE   118643   3-07-88   5:10a
  6000.  C1L      EXE   158625   3-07-88   5:10a
  6001.  C1       ERR    14393   3-07-88   5:10a
  6002.  C23      ERR     3272   3-07-88   5:10a
  6003.  C2       EXE   222515   3-07-88   5:10a
  6004.  C3       EXE   129609   3-07-88   5:10a
  6005.  BINDC    BAT     2784   3-07-88   5:10a
  6006.  BINDC    CMD     2712   3-07-88   5:10a
  6007.         15 File(s)     41984 bytes free
  6008.  
  6009.   Volume in drive A has no label
  6010.   Directory of  A:\INCLMT
  6011.  
  6012.  .            <DIR>      3-07-88   5:10a
  6013.  ..           <DIR>      3-07-88   5:10a
  6014.  SYS          <DIR>      3-07-88   5:10a
  6015.  ASSERT   H        703   3-07-88   5:10a
  6016.  BIOS     H       4866   3-07-88   5:10a
  6017.  CONIO    H       1024   3-07-88   5:10a
  6018.  CTYPE    H       2952   3-07-88   5:10a
  6019.  DIRECT   H        726   3-07-88   5:10a
  6020.  DOS      H       5917   3-07-88   5:10a
  6021.  ERRNO    H       1283   3-07-88   5:10a
  6022.  FCNTL    H       1255   3-07-88   5:10a
  6023.  FLOAT    H       6027   3-07-88   5:10a
  6024.  IO       H       1438   3-07-88   5:10a
  6025.  LIMITS   H       1553   3-07-88   5:10a
  6026.  MALLOC   H       3370   3-07-88   5:10a
  6027.  MATH     H       3709   3-07-88   5:10a
  6028.  MEMORY   H       1149   3-07-88   5:10a
  6029.  SEARCH   H       1137   3-07-88   5:10a
  6030.  SETJMP   H        915   3-07-88   5:10a
  6031.  SHARE    H        554   3-07-88   5:10a
  6032.  SIGNAL   H       1941   3-07-88   5:10a
  6033.  STDARG   H        622   3-07-88   5:10a
  6034.  STDDEF   H       1217   3-07-88   5:10a
  6035.  STDIO    H       5046   3-07-88   5:10a
  6036.  STDLIB   H       5335   3-07-88   5:10a
  6037.  STRING   H       2629   3-07-88   5:10a
  6038.  TIME     H       2693   3-07-88   5:10a
  6039.  VARARGS  H        650   3-07-88   5:10a
  6040.  PROCESS  H       2370   3-07-88   5:10a
  6041.  OS2      H        707   3-07-88   5:10a
  6042.  OS2DEF   H       5891   3-07-88   5:10a
  6043.  BSE      H       1139   3-07-88   5:10a
  6044.  BSEDOS   H      17730   3-07-88   5:10a
  6045.  BSEERR   H      20940   3-07-88   5:10a
  6046.  BSESUB   H      11512   3-07-88   5:10a
  6047.         35 File(s)     41984 bytes free
  6048.  
  6049.  :::::::::::::::::::::::::::::::::::::::
  6050.  
  6051.  (Disk 14 of 14)  -  MS OS/2 Libraries
  6052.  
  6053.   Volume in drive A has no label
  6054.   Directory of  A:\
  6055.  
  6056.  EXAMPLE      <DIR>      3-07-88   5:10a
  6057.  SLIBCP   LIB   119999   3-07-88   5:10a
  6058.  MLIBCP   LIB   121535   3-07-88   5:10a
  6059.  CLIBCP   LIB   129257   3-07-88   5:10a
  6060.  LLIBCP   LIB   130793   3-07-88   5:10a
  6061.  APILMR   OBJ      105   3-07-88   5:10a
  6062.  API      LIB    81408   3-07-88   5:10a
  6063.  CDLLSUPP LIB     9475   3-07-88   5:10a
  6064.  LLIBCDLL LIB   178143   3-07-88   5:10a
  6065.  LLIBCMT  LIB   198913   3-07-88   5:10a
  6066.  CDLLOBJS LIB   203063   3-07-88   5:10a
  6067.  CDLLOBJS DEF     4397   3-07-88   5:10a
  6068.  CDLLOBJS CMD     2048   3-07-88   5:10a
  6069.  CRTEXE   OBJ     1089   3-07-88   5:10a
  6070.  CRTDLL   OBJ      577   3-07-88   5:10a
  6071.  CRTLIB   OBJ     1177   3-07-88   5:10a
  6072.         16 File(s)         0 bytes free
  6073.  
  6074.   Volume in drive A has no label
  6075.   Directory of  A:\EXAMPLE
  6076.  
  6077.  .            <DIR>      3-07-88   5:10a
  6078.  ..           <DIR>      3-07-88   5:10a
  6079.  MHELLO   C       2990   3-07-88   5:10a
  6080.  MKMHELLO CMD      433   3-07-88   5:10a
  6081.  STMAIN   C        825   3-07-88   5:10a
  6082.  STMAIN   DEF       41   3-07-88   5:10a
  6083.  STDLL    C        393   3-07-88   5:10a
  6084.  STDLL    DEF      124   3-07-88   5:10a
  6085.  MKSTDLL  CMD      714   3-07-88   5:10a
  6086.  MTMAIN   C        735   3-07-88   5:10a
  6087.  MTMAIN   DEF       41   3-07-88   5:10a
  6088.  MTDLL    C        393   3-07-88   5:10a
  6089.  MTDLL    DEF      124   3-07-88   5:10a
  6090.  MKMTDLL  CMD     1587   3-07-88   5:10a
  6091.  SNAP     C      13083   3-07-88   5:10a
  6092.  MAKESNAP CMD     2148   3-07-88   5:10a
  6093.         16 File(s)         0 bytes free
  6094.  
  6095.  
  6096.  134. Getting the Address of a Function with FP_SEG and FP_OFF
  6097.  
  6098.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  6099.  Operating System:   MS-DOS              | OS/2
  6100.  Flags: ENDUSER |
  6101.  Last Modified: 12-OCT-1988    ArticleIdent: Q35295
  6102.  
  6103.  To get the address of a function, you may set a pointer to the
  6104.  function by using FP_SEG and FP_OFF to get the segment and offset
  6105.  for the function.
  6106.  
  6107.  The following sample code demonstrates this process:
  6108.  
  6109.  #include <dos.h>
  6110.  #include <stdio.h>
  6111.  
  6112.  int foo();
  6113.  int (*foo_ptr)();
  6114.  unsigned int seg_val;
  6115.  unsigned int off_val;
  6116.  
  6117.  void main(void);
  6118.  void main(void)
  6119.  {
  6120.      /* set the pointer to the function */
  6121.      foo_ptr = foo;
  6122.  
  6123.      /* use FP_SEG() and FP_OFF() to get segment and offset */
  6124.      seg_val = FP_SEG(foo_ptr);
  6125.      off_val = FP_OFF(foo_ptr);
  6126.      printf("Segment is %d; Offset is %d\n", seg_val, off_val);
  6127.  }
  6128.  
  6129.  int foo()
  6130.      {}
  6131.  
  6132.  
  6133.  135. Differences between C signal() Function and DosSetSigHandler
  6134.  
  6135.  Product Version(s): 5.10
  6136.  Operating System:   OS/2
  6137.  Flags: ENDUSER |
  6138.  Last Modified: 12-OCT-1988    ArticleIdent: Q35297
  6139.  
  6140.  Question:
  6141.  
  6142.  I have some questions concerning signal handling in OS/2, and
  6143.  differences between the C run-time library signal() function and the
  6144.  OS/2 API routine DosSetSigHandler. What are the differences; what are
  6145.  the results of using these routines?
  6146.  
  6147.  Response:
  6148.  
  6149.  Under OS/2, the C run-time library signal() function has fewer options
  6150.  and different behavior than the OS/2 API DosSetSigHandler function.
  6151.  The signal() function is described in the next few paragraphs, then
  6152.  the features of DosSetSigHandler are explained.
  6153.  
  6154.  Features of the C Run-Time Library Signal() Function in OS/2
  6155.  
  6156.  The C run-time library signal() function only is for use in
  6157.  single-thread applications, and for floating-point exception handling
  6158.  in Dynamic Link Libraries.
  6159.  
  6160.  Using strictly C run-time functions, such as signal() and spawnlp(),
  6161.  signal handling in OS/2 is accomplished (or not, by default) by thread
  6162.  1 of each process. This behavior occurs whether the process was invoked
  6163.  from the operating system or was spawned by another process.
  6164.  
  6165.  As a result, while this process is running, a child process is
  6166.  unaffected by how its parent handles signals; if a signal is generated
  6167.  during the execution of the child, the child either handles it with
  6168.  its own signal handler, or if it was spawned with P_WAIT or P_NOWAIT,
  6169.  control returns to the parent process. (However, no control returns to
  6170.  the parent process's signal handler, which is unlike the
  6171.  DosSetSigHandler's effect.) Once the parent resumes execution, its
  6172.  signal handler once again will be in effect for any newly generated
  6173.  signals.
  6174.  
  6175.  For example, say a parent process sets up a signal handler, then
  6176.  spawns MAKE. While running MAKE, if a CTRL+C signal occurs, either the
  6177.  process spawned by MAKE such as the CL driver, or MAKE itself will be
  6178.  interrupted. If CL is interrupted by CTRL+C, it returns an error to
  6179.  MAKE and MAKE terminates. If MAKE itself is interrupted, it
  6180.  terminates. In either case, control will be returned to the parent
  6181.  process after the point where it spawned MAKE, and the parent resumes
  6182.  execution. The parent's signal handler will handle signals generated
  6183.  after it starts executing again, but none of the signals generated by
  6184.  the child are kept by the system and returned to the parent.
  6185.  
  6186.  If both the parent and child have no signal handler, if the child is
  6187.  spawned with P_WAIT or P_NOWAIT and it is terminated without hanging
  6188.  the system, then control goes back to the parent. The parent continues
  6189.  executing until it is terminated.
  6190.  
  6191.  Features of OS/2's DosSetSigHandler
  6192.  
  6193.  The OS/2 API routine DosSetSigHandler has more options than the C
  6194.  run-time library signal() function. A child process will inherit
  6195.  (i.e., use) the parent's signal handler, or the closest ancestor's
  6196.  defined signal handler if its immediate parent didn't create one.
  6197.  
  6198.  If the parent called DosSetSigHandler to handle CTRL+C with Action = 0
  6199.  (install the system default action, in this case to terminate the
  6200.  process), a CTRL+C issued in the parent or child will use the parent's
  6201.  handler. If the CTRL+C occurred in the child, the child will be
  6202.  terminated (by default) when the parent's signal handler is called.
  6203.  The parent will resume execution after its signal handler function is
  6204.  completed in a similar manner to DOS. However, the child may install
  6205.  its own signal handler rather than using the parent's.
  6206.  
  6207.  If you use Action = 2 (install the specified signal handler
  6208.  for the given signal) for handling CTRL+C in the parent process,
  6209.  hitting CTRL+C in its child causes the child to pause while the
  6210.  handler is executed; however, the child won't terminate. For Action =
  6211.  1 (ignore signal) in a DosSetSigHandler call by the parent for CTRL+C,
  6212.  CTRL+C is ignored in the child as well as the parent.
  6213.  
  6214.  If neither parent nor child sets up a signal handler, CTRL+C will kill
  6215.  them all regardless of which process gets the CTRL+C. This action
  6216.  occurs because signal handlers are being inherited, and signals are
  6217.  either handled in the current process if it has a handler, or
  6218.  effectively passed back up the process subtree (from child to parent)
  6219.  until a process is reached that has a CTRL+C signal handler.
  6220.  
  6221.  Because the default action for CTRL+C is to terminate the process, a
  6222.  process without a CTRL+C handler gets terminated, and the CTRL+C
  6223.  signal effectively gets passed up to its parent. If the parent doesn't
  6224.  have a CTRL+C handler, it terminates and passes control to its parent.
  6225.  If no one set up a signal handler, the original parent at the root of
  6226.  the process subtree handles the signal, and the default action is to
  6227.  return to the system.
  6228.  
  6229.  Some precautions for signal handling are recommended. After setting up
  6230.  a signal handler, avoid making system calls from thread 1, especially
  6231.  time-consuming calls such as waiting for keyboard input or some other
  6232.  event. If OS/2 is executing code for a system call at Ring 0, it
  6233.  cannot run a signal handler at Ring 3. Instead, executing the system
  6234.  code is completed, or aborted if it is a time-consuming call (which
  6235.  could result in incomplete I/O), and then the signal is handled.
  6236.  
  6237.  Another particularly bad scenario is if thread 1 blocks a critical
  6238.  section of code with a RAM semaphore, is interrupted and handles a
  6239.  signal, and then the signal handler resumes execution elsewhere so
  6240.  that the RAM semaphore is not cleared and the critical section remains
  6241.  blocked. If thread 1 must run critical sections of code, it should
  6242.  call DosHoldSignal to disable the signal prior to entering the
  6243.  critical section.
  6244.  
  6245.  
  6246.  136. Using PRINT SCREEN Key to Print CGA Graphics
  6247.  
  6248.  Product Version(s): 5.00 5.10
  6249.  Operating System:   MS-DOS
  6250.  Flags: ENDUSER |
  6251.  Last Modified: 27-OCT-1988    ArticleIdent: Q35303
  6252.  
  6253.  To print graphics generated by a C program using the PRINT SCREEN key,
  6254.  you must first install GRAPHICS.COM (supplied by your DOS). This
  6255.  process only will work with the CGA modes. Hercules, EGA, and VGA modes
  6256.  will not print with this method; you must obtain a third party, public
  6257.  domain, or shareware program to print graphics from these modes.
  6258.  
  6259.  In the DOS environment, PRINT SCREEN prints any text screen to an
  6260.  attached printer hooked to PRN. This function isn't able to interpret
  6261.  a graphic screen to the printer because a graphic screen is defined
  6262.  and produced differently than a text screen.
  6263.  
  6264.  A unit of area is defined by a pixel rather than a character. (This
  6265.  can be noticed by the way a text screen is described "80 columns by 25
  6266.  rows" as opposed to a graphics screen "640 pixels by 200 pixels.")
  6267.  
  6268.  DOS supplies a TSR that allows the PRINT SCREEN to interpret a graphic
  6269.  screen. This is called GRAPHICS.COM. When it is installed, it will
  6270.  interpret a CGA graphic screen to a printer attached to PRN. This
  6271.  utility must be installed before running a C program that draws a
  6272.  graphic screen in the CGA modes, i.e., the program must have specified
  6273.  a _setvideomode to _MRES4COLOR, _MRESNOCOLOR, or _HRESBW. Any of the
  6274.  other video modes will require some other utility to interpret the
  6275.  screen for the printer.
  6276.  
  6277.  It also should be noted that GRAPHICS.COM was written to write to an
  6278.  IBM Personal Graphics or IBM Personal Color Printer. It may be
  6279.  necessary on some other printers to set some switch settings, if
  6280.  available, to emulate either of these printers. The printer manual for
  6281.  the specific printer should be consulted in these cases.
  6282.  
  6283.  
  6284.  137. Libraries Created by IMPLIB Are Different than those from LIB
  6285.  
  6286.  Product Version(s): 5.10
  6287.  Operating System:   MS-DOS
  6288.  Flags: ENDUSER | SR# S880908-4
  6289.  Last Modified: 26-SEP-1988    ArticleIdent: Q35539
  6290.  
  6291.  The only similarity between Libraries created by IMPLIB and libraries
  6292.  created by LIB is the filename extension ".LIB".
  6293.  
  6294.  Libraries created by IMPLIB only contain the names of functions and
  6295.  modules to satisfy the linker. The actual code is brought in later by
  6296.  loading Dynamic Link Libraries (DLL).
  6297.  
  6298.  Regular libraries contain all the code for the functions. One or more
  6299.  functions are contained in a module (e.g. object file). The code for
  6300.  the entire module containing a called function is statically linked
  6301.  into the executable file.
  6302.  
  6303.  You cannot use LIB to get any information about libraries created by
  6304.  IMPLIB. You cannot combine IMPLIB and LIB libraries. To see what
  6305.  modules are in an IMPLIB library, use the type command to display the
  6306.  .LIB file; it is a text file.
  6307.  
  6308.  
  6309.  138. Example Incorrect for the write() Function
  6310.  
  6311.  Product Version(s): 5.00 5.10 | 5.10
  6312.  Operating System:   MS-DOS    | OS/2
  6313.  Flags: ENDUSER | docerr
  6314.  Last Modified: 26-SEP-1988    ArticleIdent: Q35545
  6315.  
  6316.  The example for the write() function on Page 641 of the "Microsoft C
  6317.  5.1 Optimizing Compiler Run-Time Library Reference" is incorrect; it
  6318.  causes OS/2 to generate a General Protection (GP) fault.
  6319.  
  6320.  This example fails in OS/2 because it attempts to write 60,000 bytes
  6321.  from a buffer of size 6,000 bytes. In effect, it is attempting to read
  6322.  beyond the buffer of size 6000, causing the GP fault. In DOS, this
  6323.  error may go undetected, but an extra 54,000 bytes of random garbage
  6324.  may be written to the file.
  6325.  
  6326.  To work around this problem, change the number of bytes to write from
  6327.  60,000 bytes to 6000 bytes.
  6328.  
  6329.  
  6330.  139. The Total Bytes in MAP File Differs from Load Size in EXEMOD
  6331.  
  6332.  Product Version(s): 4.00 5.00 5.10
  6333.  Operating System:   MS-DOS
  6334.  Flags: ENDUSER | SR# S880908-4
  6335.  Last Modified: 19-SEP-1988    ArticleIdent: Q35628
  6336.  
  6337.  Question:
  6338.  
  6339.  When I run EXEMOD on my executable file and look at the minimum load
  6340.  size, it always is greater than or equal to the size of my executable
  6341.  listed in my MAP file. Why?
  6342.  
  6343.  Response:
  6344.  
  6345.  EXEMOD reflects the minimum load size of a program that is rounded up
  6346.  to the 16-byte paragraph level. As a result, the minimum load size
  6347.  will be up to 15-bytes larger than the size of the program indicated
  6348.  in your MAP file.
  6349.  
  6350.  
  6351.  140. Process "exit" Values Must Lie Between 0 and 255 Inclusive
  6352.  
  6353.  Product Version(s): 4.00 5.00 5.10 | 4.00 5.00 5.10
  6354.  Operating System:   MS-DOS         | OS/2
  6355.  Flags: ENDUSER | S_QUICKC
  6356.  Last Modified: 29-DEC-1988    ArticleIdent: Q39469
  6357.  
  6358.  Problem:
  6359.  
  6360.  I am testing the exit value of a process. This value is not accurate
  6361.  for values above 255.
  6362.  
  6363.  Response:
  6364.  
  6365.  Exit values must range between 0 and 255 inclusive. This limitation
  6366.  has its roots in the "terminate with return code" interrupt function
  6367.  (interrupt 21H, function 4CH). Using this function, exit values are
  6368.  specified in the AL register. The AL register allows values from 0 to
  6369.  255. All Microsoft C programs under DOS terminate using this function.
  6370.  
  6371.  Under OS/2, the same limitation exists. Although OS/2 does not use
  6372.  interrupts as DOS does, the reasoning is analogous.
  6373.  
  6374.  Exit values can be tested using the functions spawnl, spawnle, spawnlp,
  6375.  spawnlpe, spawnv, spawnve, spawnvp, and spawnvpe. Also, batch files may
  6376.  test exit values using the IF ERRORLEVEL statement.
  6377.  
  6378.  
  6379.  141. Incorrect Function Declaration
  6380.  
  6381.  Product Version(s): 5.00 5.10 | 5.10
  6382.  Operating System:   MS-DOS    | OS/2
  6383.  Flags: ENDUSER | docerr h_fortran h_masm s_pascal
  6384.  Last Modified: 23-SEP-1988    ArticleIdent: Q35730
  6385.  
  6386.  On Page 66 of the "Microsoft Mixed-Language Programmer's Guide"
  6387.  provided with C Versions 5.00 and 5.10, FORTRAN Versions 4.0x and
  6388.  4.10, MASM Versions 5.00 and 5.10, and Pascal Version 4.00, the
  6389.  example program given in section 5.4.2 "Calling C from Pascal --
  6390.  Function Call" is incorrect. If the Pascal source code in the manual
  6391.  is compiled, the following errors will occur on the function
  6392.  declaration line:
  6393.  
  6394.                     function Fact (n : integer)  [C]; extern;
  6395.                                                ^ ^          ^
  6396.   Warning 173  Insert:     ____________________| |          |
  6397.      (the compiler is expecting a colon)         |          |
  6398.                                                  |          |
  6399.   315  Type unknown or invalid assumed integer __|          |
  6400.        Begin Skip                                           |
  6401.                                                             |
  6402.   187  End Skip    _________________________________________|
  6403.  
  6404.  The function declaration in the Pascal program is missing its return
  6405.  value. If the line is corrected to look as follows the program works
  6406.  properly:
  6407.  
  6408.  function Fact (n : integer) : integer  [C]; extern;
  6409.  
  6410.  
  6411.  142. Directory Listing for C 5.10 Distribution Disks (3.5-Inch)
  6412.  
  6413.  Product Version(s): 5.10   | 5.10
  6414.  Operating System:   MS-DOS | OS/2
  6415.  Flags: ENDUSER |
  6416.  Last Modified: 23-SEP-1988    ArticleIdent: Q35753
  6417.  
  6418.  The following is a listing of the directories for each of the
  6419.  Microsoft C Version 5.10 Optimizing Compiler distribution disks
  6420.  (3.5-inch disks). The information is the resulting output when the DOS
  6421.  command "dir" is performed on each directory and subdirectory.
  6422.  
  6423.  A line of colons (:::::) separates each disk, and subdirectories are
  6424.  listed below their parent directory. The first line of each disk
  6425.  description is the name of the disk as it is printed on the label;
  6426.  however, information in parentheses is supplemental and not contained
  6427.  on the disk label.
  6428.  
  6429.  :::::::::::::::::::::::::::::::::::::::
  6430.  C 5.10 distribution disks, 3.5-inch disks
  6431.  :::::::::::::::::::::::::::::::::::::::
  6432.  
  6433.  (Disk 1 of 10)  -  Setup, Include Files, and Startup Source Code
  6434.  
  6435.   Volume in drive B has no label.
  6436.   Directory of B:\
  6437.  
  6438.  STARTUP      <DIR>      3-07-88   5:10a
  6439.  INCLUDE      <DIR>      3-07-88   5:10a
  6440.  README   DOC    63358   3-07-88   5:10a
  6441.  UTILITY  DOC    17794   3-07-88   5:10a
  6442.  PACKING  LST    11504   3-07-88   5:10a
  6443.  CL       EXE    31329   3-07-88   5:10a
  6444.  CL       HLP     2169   3-07-88   5:10a
  6445.  CL       ERR     2276   3-07-88   5:10a
  6446.  C1       EXE   114521   3-07-88   5:10a
  6447.  C23      ERR     3272   3-07-88   5:10a
  6448.  SETUP    EXE    93033   3-07-88   5:10a
  6449.  SETUP    DOC    15179   3-07-88   5:10a
  6450.       12 File(s)   37888 bytes free
  6451.  
  6452.   Volume in drive B has no label.
  6453.   Directory of B:\INCLUDE
  6454.  
  6455.  .            <DIR>      3-07-88   5:10a
  6456.  ..           <DIR>      3-07-88   5:10a
  6457.  SYS          <DIR>      3-07-88   5:10a
  6458.  ASSERT   H        699   3-07-88   5:10a
  6459.  BIOS     H       4866   3-07-88   5:10a
  6460.  CONIO    H        952   3-07-88   5:10a
  6461.  CTYPE    H       2465   3-07-88   5:10a
  6462.  DIRECT   H        690   3-07-88   5:10a
  6463.  DOS      H       5917   3-07-88   5:10a
  6464.  ERRNO    H       1283   3-07-88   5:10a
  6465.  FCNTL    H       1255   3-07-88   5:10a
  6466.  FLOAT    H       6011   3-07-88   5:10a
  6467.  GRAPH    H       7480   3-07-88   5:10a
  6468.  IO       H       1294   3-07-88   5:10a
  6469.  LIMITS   H       1553   3-07-88   5:10a
  6470.  MALLOC   H       3097   3-07-88   5:10a
  6471.  MATH     H       3324   3-07-88   5:10a
  6472.  MEMORY   H       1065   3-07-88   5:10a
  6473.  SEARCH   H       1025   3-07-88   5:10a
  6474.  SETJMP   H        907   3-07-88   5:10a
  6475.  SHARE    H        554   3-07-88   5:10a
  6476.  SIGNAL   H       1905   3-07-88   5:10a
  6477.  STDARG   H        614   3-07-88   5:10a
  6478.  STDDEF   H       1100   3-07-88   5:10a
  6479.  STDIO    H       4500   3-07-88   5:10a
  6480.  STDLIB   H       4900   3-07-88   5:10a
  6481.  STRING   H       2209   3-07-88   5:10a
  6482.  TIME     H       2342   3-07-88   5:10a
  6483.  VARARGS  H        642   3-07-88   5:10a
  6484.  PROCESS  H       1988   3-07-88   5:10a
  6485.  OS2      H        707   3-07-88   5:10a
  6486.  OS2DEF   H       5891   3-07-88   5:10a
  6487.  BSE      H       1139   3-07-88   5:10a
  6488.  BSEDOS   H      17730   3-07-88   5:10a
  6489.  BSEERR   H      20940   3-07-88   5:10a
  6490.  BSESUB   H      11512   3-07-88   5:10a
  6491.       36 File(s)   37888 bytes free
  6492.  
  6493.   Volume in drive B has no label.
  6494.   Directory of B:\INCLUDE\SYS
  6495.  
  6496.  .            <DIR>      3-07-88   5:10a
  6497.  ..           <DIR>      3-07-88   5:10a
  6498.  LOCKING  H        573   3-07-88   5:10a
  6499.  STAT     H       1497   3-07-88   5:10a
  6500.  TIMEB    H        844   3-07-88   5:10a
  6501.  TYPES    H        849   3-07-88   5:10a
  6502.  UTIME    H       1061   3-07-88   5:10a
  6503.       7 File(s)   37888 bytes free
  6504.  
  6505.   Volume in drive B has no label.
  6506.   Directory of B:\STARTUP
  6507.  
  6508.  .            <DIR>      3-07-88   5:10a
  6509.  ..           <DIR>      3-07-88   5:10a
  6510.  DOS          <DIR>      3-07-88   5:10a
  6511.  OS2          <DIR>      3-07-88   5:10a
  6512.  FILE2    H       1027   3-07-88   5:10a
  6513.  MSDOS    H       6849   3-07-88   5:10a
  6514.  REGISTER H        922   3-07-88   5:10a
  6515.  STARTUP  BAT     1663   3-07-88   5:10a
  6516.  MAKEFILE         4148   3-07-88   5:10a
  6517.  CHKSTK   ASM     2044   3-07-88   5:10a
  6518.  CHKSUM   ASM     3524   3-07-88   5:10a
  6519.  NULBODY  C         13   3-07-88   5:10a
  6520.  README   DOC     3199   3-07-88   5:10a
  6521.  MSDOS    INC     6181   3-07-88   5:10a
  6522.  CMACROS  INC    12066   3-07-88   5:10a
  6523.  BRKCTL   INC      784   3-07-88   5:10a
  6524.  VERSION  INC      503   3-07-88   5:10a
  6525.  WILD     C       7182   3-07-88   5:10a
  6526.  _FILE    C       1691   3-07-88   5:10a
  6527.  CRT0FP   ASM     2223   3-07-88   5:10a
  6528.  FMSGHDR  ASM     2429   3-07-88   5:10a
  6529.  SETARGV  ASM      971   3-07-88   5:10a
  6530.       22 File(s)   37888 bytes free
  6531.  
  6532.   Volume in drive B has no label.
  6533.   Directory of B:\STARTUP\DOS
  6534.  
  6535.  .            <DIR>      3-07-88   5:10a
  6536.  ..           <DIR>      3-07-88   5:10a
  6537.  NULBODY  LNK      149   3-07-88   5:10a
  6538.  STDENVP  ASM     3780   3-07-88   5:10a
  6539.  CRT0     ASM     7612   3-07-88   5:10a
  6540.  CRT0DAT  ASM    14175   3-07-88   5:10a
  6541.  CRT0MSG  ASM     2840   3-07-88   5:10a
  6542.  EXECMSG  ASM     1337   3-07-88   5:10a
  6543.  NMSGHDR  ASM     3010   3-07-88   5:10a
  6544.  STDALLOC ASM     2825   3-07-88   5:10a
  6545.  STDARGV  ASM    13852   3-07-88   5:10a
  6546.       11 File(s)   37888 bytes free
  6547.  
  6548.   Volume in drive B has no label.
  6549.   Directory of B:\STARTUP\OS2
  6550.  
  6551.  .            <DIR>      3-07-88   5:10a
  6552.  ..           <DIR>      3-07-88   5:10a
  6553.  NULBODY  LNK      168   3-07-88   5:10a
  6554.  CRT0     ASM    10312   3-07-88   5:10a
  6555.  STDENVP  ASM     5362   3-07-88   5:10a
  6556.  CRT0DAT  ASM    10496   3-07-88   5:10a
  6557.  CRT0MSG  ASM     2891   3-07-88   5:10a
  6558.  EXECMSG  ASM     2231   3-07-88   5:10a
  6559.  NMSGHDR  ASM     3486   3-07-88   5:10a
  6560.  STDALLOC ASM     3245   3-07-88   5:10a
  6561.  STDARGV  ASM    13623   3-07-88   5:10a
  6562.       11 File(s)   37888 bytes free
  6563.  
  6564.  :::::::::::::::::::::::::::::::::::::::
  6565.  
  6566.  (Disk 2 of 10)  -  Compiler
  6567.  
  6568.   Volume in drive B has no label.
  6569.   Directory of B:\
  6570.  
  6571.  PATCH        <DIR>      3-07-88   5:10a
  6572.  C1       ERR    14393   3-07-88   5:10a
  6573.  C1L      EXE   149303   3-07-88   5:10a
  6574.  C3       EXE   125221   3-07-88   5:10a
  6575.  ERRMSG   DOC    17293   3-07-88   5:10a
  6576.  FPEXCEPT DOC    16254   3-07-88   5:10a
  6577.  FIXSHIFT COM      688   3-07-88   5:10a
  6578.  MSHERC   COM     6749   3-07-88   5:10a
  6579.  QLIB     DOC    12047   3-07-88   5:10a
  6580.  QLIB     EXE    24557   3-07-88   5:10a
  6581.  QLIB     INI     2905   3-07-88   5:10a
  6582.  C2       EXE   202919   3-07-88   5:10a
  6583.  QC       HLP    50649   3-07-88   5:10a
  6584.  SETENV   EXE    10870   3-07-88   5:10a
  6585.  MTDYNA   DOC    43542   3-07-88   5:10a
  6586.       15 File(s)   24576 bytes free
  6587.  
  6588.   Volume in drive B has no label.
  6589.   Directory of B:\PATCH
  6590.  
  6591.  .            <DIR>      3-07-88   5:10a
  6592.  ..           <DIR>      3-07-88   5:10a
  6593.  PATCH87  DOC     3937   3-07-88   5:10a
  6594.  PATCH87  EXE     4206   3-07-88   5:10a
  6595.  SETRHS   EXE      543   3-07-88   5:10a
  6596.  RMRHS    EXE      543   3-07-88   5:10a
  6597.  STKPAT   BAT       94   3-07-88   5:10a
  6598.  STKPAT   SCR       30   3-07-88   5:10a
  6599.  PTRACE87 PAT      188   3-07-88   5:10a
  6600.  PATCH320 DOC     2169   3-07-88   5:10a
  6601.  OS2PATCH EXE     1069   3-07-88   5:10a
  6602.  OS2PATCH DOC     1401   3-07-88   5:10a
  6603.       12 File(s)   24576 bytes free
  6604.  
  6605.  :::::::::::::::::::::::::::::::::::::::
  6606.  
  6607.  (Disk 3 of 10)  -  Utilities
  6608.  
  6609.   Volume in drive B has no label.
  6610.   Directory of B:\
  6611.  
  6612.  EXT          <DIR>      3-07-88   5:10a
  6613.  INI          <DIR>      3-07-88   5:10a
  6614.  ERROUT   EXE    10729   3-07-88   5:10a
  6615.  EXEHDR   EXE    29942   3-07-88   5:10a
  6616.  EXEMOD   EXE    12336   3-07-88   5:10a
  6617.  EXEPACK  EXE    14803   3-07-88   5:10a
  6618.  IMPLIB   EXE    30166   3-07-88   5:10a
  6619.  LIB      EXE    49661   3-07-88   5:10a
  6620.  LINK     EXE   117001   3-07-88   5:10a
  6621.  MAKE     EXE    38613   3-07-88   5:10a
  6622.  MOUSE    COM    14545   3-07-88   5:10a
  6623.  README   QC     30351   3-07-88   5:10a
  6624.  BIND     EXE    36946   3-07-88   5:10a
  6625.  CALLTREE EXE    31233   3-07-88   5:10a
  6626.  ECH      EXE    19351   3-07-88   5:10a
  6627.  EXP      EXE    32220   3-07-88   5:10a
  6628.  M        EXE    94821   3-07-88   5:10a
  6629.  MEGREP   EXE    31915   3-07-88   5:10a
  6630.  RM       EXE    24884   3-07-88   5:10a
  6631.  UNDEL    EXE    30046   3-07-88   5:10a
  6632.       20 File(s)   21504 bytes free
  6633.  
  6634.   Volume in drive B has no label.
  6635.   Directory of B:\EXT
  6636.  
  6637.  .            <DIR>      3-07-88   5:10a
  6638.  ..           <DIR>      3-07-88   5:10a
  6639.  EXT      DOC    15877   3-07-88   5:10a
  6640.  EXT      H       8730   3-07-88   5:10a
  6641.  EXTHDR   OBJ     1893   3-07-88   5:10a
  6642.  EXTHDRP  OBJ     2021   3-07-88   5:10a
  6643.  SKEL     C       2457   3-07-88   5:10a
  6644.  SKEL     DEF      211   3-07-88   5:10a
  6645.  WS       DLL     2609   3-07-88   5:10a
  6646.  WS       ZXT     2084   3-07-88   5:10a
  6647.       10 File(s)   21504 bytes free
  6648.  
  6649.   Volume in drive B has no label.
  6650.   Directory of B:\INI
  6651.  
  6652.  .            <DIR>      3-07-88   5:10a
  6653.  ..           <DIR>      3-07-88   5:10a
  6654.  BRIEF    INI     2094   3-07-88   5:10a
  6655.  EPSILON  INI      978   3-07-88   5:10a
  6656.  QUICK    INI     1058   3-07-88   5:10a
  6657.       5 File(s)   21504 bytes free
  6658.  
  6659.  :::::::::::::::::::::::::::::::::::::::
  6660.  
  6661.  (Disk 4 of 10)  -  Libraries (Small, Medium, Compact, and Large
  6662.                                Models)
  6663.  
  6664.   Volume in drive B has no label.
  6665.   Directory of B:\
  6666.  
  6667.  SLIBCR   LIB   132047   3-07-88   5:10a
  6668.  SLIBFA   LIB    46089   3-07-88   5:10a
  6669.  SVARSTCK OBJ      507   3-07-88   5:10a
  6670.  MLIBCR   LIB   133071   3-07-88   5:10a
  6671.  MLIBFA   LIB    46601   3-07-88   5:10a
  6672.  MVARSTCK OBJ      507   3-07-88   5:10a
  6673.  CLIBCR   LIB   141301   3-07-88   5:10a
  6674.  CVARSTCK OBJ      487   3-07-88   5:10a
  6675.  LLIBCR   LIB   142837   3-07-88   5:10a
  6676.  LLIBFA   LIB    47625   3-07-88   5:10a
  6677.  LVARSTCK OBJ      487   3-07-88   5:10a
  6678.       11 File(s)   33792 bytes free
  6679.  
  6680.  :::::::::::::::::::::::::::::::::::::::
  6681.  
  6682.  (Disk 5 of 10)  -  Floating-Point Libraries and Microsoft QuickC for
  6683.                     MS-DOS
  6684.  
  6685.   Volume in drive B has no label.
  6686.   Directory of B:\
  6687.  
  6688.  FORTRAN      <DIR>      3-07-88   5:10a
  6689.  EM       LIB    16921   3-07-88   5:10a
  6690.  87       LIB     4121   3-07-88   5:10a
  6691.  DOSCALLS LIB    29184   3-07-88   5:10a
  6692.  GRAPHICS LIB    59357   3-07-88   5:10a
  6693.  LIBH     LIB    14209   3-07-88   5:10a
  6694.  QUICKLIB OBJ     7917   3-07-88   5:10a
  6695.  SETARGV  OBJ      143   3-07-88   5:10a
  6696.  BINMODE  OBJ      127   3-07-88   5:10a
  6697.  SLIBFP   LIB    37281   3-07-88   5:10a
  6698.  MLIBFP   LIB    38305   3-07-88   5:10a
  6699.  CLIBFA   LIB    47113   3-07-88   5:10a
  6700.  CLIBFP   LIB    38307   3-07-88   5:10a
  6701.  LLIBFP   LIB    39331   3-07-88   5:10a
  6702.  QC       EXE   326656   3-07-88   5:10a
  6703.  QCL      EXE    28065   3-07-88   5:10a
  6704.  QCL      HLP     1456   3-07-88   5:10a
  6705.       17 File(s)   25600 bytes free
  6706.  
  6707.   Volume in drive B has no label.
  6708.   Directory of B:\FORTRAN
  6709.  
  6710.  .            <DIR>      3-07-88   5:10a
  6711.  ..           <DIR>      3-07-88   5:10a
  6712.  MDBGMSG  OBJ      540   3-07-88   5:10a
  6713.  LDBGMSG  OBJ      544   3-07-88   5:10a
  6714.  F4COMPAT BAT     3107   3-07-88   5:10a
  6715.       5 File(s)   25600 bytes free
  6716.  
  6717.  :::::::::::::::::::::::::::::::::::::::
  6718.  
  6719.  (Disk 6 of 10)  -  Microsoft CodeView for MS-DOS with Tutorial
  6720.  
  6721.   Volume in drive B has no label.
  6722.   Directory of B:\
  6723.  
  6724.  SAMPLE       <DIR>      3-07-88   5:10a
  6725.  SOURCE       <DIR>      3-07-88   5:10a
  6726.  CV       EXE   232896   3-07-88   5:10a
  6727.  ILINK    EXE    88929   3-07-88   5:10a
  6728.  LINK     EXE    65539   3-07-88   5:10a
  6729.  EXEC     EXE     9299   3-07-88   5:10a
  6730.  CV       HLP    21552   3-07-88   5:10a
  6731.  CVPACK   EXE    49400   3-07-88   5:10a
  6732.       8 File(s)   18432 bytes free
  6733.  
  6734.   Volume in drive B has no label.
  6735.   Directory of B:\SAMPLE
  6736.  
  6737.  .            <DIR>      3-07-88   5:10a
  6738.  ..           <DIR>      3-07-88   5:10a
  6739.  CODEVIEW DOC    12928   3-07-88   5:10a
  6740.  ADAPT    BAT      133   3-07-88   5:10a
  6741.  DEMOB    BAT      254   3-07-88   5:10a
  6742.  LIFEB    BAT      336   3-07-88   5:10a
  6743.  LIFEEB   BAT      402   3-07-88   5:10a
  6744.  MENU     BAT      550   3-07-88   5:10a
  6745.  SAMPLE   BAT     1059   3-07-88   5:10a
  6746.  LIFE     C      14713   3-07-88   5:10a
  6747.  LIFE     EXE    33237   3-07-88   5:10a
  6748.  LIFE     R       5282   3-07-88   5:10a
  6749.  C_AUTO   CV      3571   3-07-88   5:10a
  6750.  E_AUTO   CV      6788   3-07-88   5:10a
  6751.  L_AUTO   CV     13272   3-07-88   5:10a
  6752.  M_AUTO   CV       733   3-07-88   5:10a
  6753.  Q_AUTO   CV        15   3-07-88   5:10a
  6754.  S_AUTO   CV      9091   3-07-88   5:10a
  6755.  RESPOND  COM      124   3-07-88   5:10a
  6756.  S1       @@@      230   3-07-88   5:10a
  6757.  S12      @@@      926   3-07-88   5:10a
  6758.  S13      @@@      368   3-07-88   5:10a
  6759.  S14      @@@      520   3-07-88   5:10a
  6760.  S2       @@@      752   3-07-88   5:10a
  6761.  S3       @@@      276   3-07-88   5:10a
  6762.  S4       @@@      354   3-07-88   5:10a
  6763.  S5       @@@      554   3-07-88   5:10a
  6764.  S6       @@@      432   3-07-88   5:10a
  6765.  S7       @@@      427   3-07-88   5:10a
  6766.  S8       @@@      479   3-07-88   5:10a
  6767.  S9       @@@      865   3-07-88   5:10a
  6768.       31 File(s)   18432 bytes free
  6769.  
  6770.   Volume in drive B has no label.
  6771.   Directory of B:\SOURCE
  6772.  
  6773.  .            <DIR>      3-07-88   5:10a
  6774.  ..           <DIR>      3-07-88   5:10a
  6775.  SAMPLES  DOC     1760   3-07-88   5:10a
  6776.  CFLOW    C      44796   3-07-88   5:10a
  6777.  CFLOW    DOC     3764   3-07-88   5:10a
  6778.  DEMO     C        419   3-07-88   5:10a
  6779.  EMOEM    ASM    12129   3-07-88   5:10a
  6780.  GRDEMO   C      20907   3-07-88   5:10a
  6781.  SIEVE    C        788   3-07-88   5:10a
  6782.  SORTDEMO C      25399   3-07-88   5:10a
  6783.       10 File(s)   18432 bytes free
  6784.  
  6785.  :::::::::::::::::::::::::::::::::::::::
  6786.  
  6787.  (Disk 7 of 10)  -  MS OS/2 Compiler
  6788.  
  6789.   Volume in drive B has no label.
  6790.   Directory of B:\
  6791.  
  6792.  CL       EXE    33900   3-07-88   5:10a
  6793.  CL       ERR     2276   3-07-88   5:10a
  6794.  CL       HLP     2169   3-07-88   5:10a
  6795.  C1       EXE   118643   3-07-88   5:10a
  6796.  C1L      EXE   158625   3-07-88   5:10a
  6797.  C1       ERR    14393   3-07-88   5:10a
  6798.  C23      ERR     3272   3-07-88   5:10a
  6799.  C2       EXE   222515   3-07-88   5:10a
  6800.  C3       EXE   129609   3-07-88   5:10a
  6801.  BINDC    BAT     2784   3-07-88   5:10a
  6802.  BINDC    CMD     2712   3-07-88   5:10a
  6803.       11 File(s)   32768 bytes free
  6804.  
  6805.  :::::::::::::::::::::::::::::::::::::::
  6806.  
  6807.  (Disk 8 of 10)  -  Microsoft CodeView for MS OS/2, Microsoft Editor,
  6808.                     and Include Files
  6809.  
  6810.   Volume in drive B has no label.
  6811.   Directory of B:\
  6812.  
  6813.  INCLMT       <DIR>      3-07-88   5:10a
  6814.  CVP      EXE   222505   3-07-88   5:10a
  6815.  CVP      HLP    21552   3-07-88   5:10a
  6816.  MEP      EXE    97063   3-07-88   5:10a
  6817.       4 File(s)   242688 bytes free
  6818.  
  6819.   Volume in drive B has no label.
  6820.   Directory of B:\INCLMT
  6821.  
  6822.  .            <DIR>      3-07-88   5:10a
  6823.  ..           <DIR>      3-07-88   5:10a
  6824.  SYS          <DIR>      3-07-88   5:10a
  6825.  ASSERT   H        703   3-07-88   5:10a
  6826.  BIOS     H       4866   3-07-88   5:10a
  6827.  CONIO    H       1024   3-07-88   5:10a
  6828.  CTYPE    H       2952   3-07-88   5:10a
  6829.  DIRECT   H        726   3-07-88   5:10a
  6830.  DOS      H       5917   3-07-88   5:10a
  6831.  ERRNO    H       1283   3-07-88   5:10a
  6832.  FCNTL    H       1255   3-07-88   5:10a
  6833.  FLOAT    H       6027   3-07-88   5:10a
  6834.  IO       H       1438   3-07-88   5:10a
  6835.  LIMITS   H       1553   3-07-88   5:10a
  6836.  MALLOC   H       3370   3-07-88   5:10a
  6837.  MATH     H       3709   3-07-88   5:10a
  6838.  MEMORY   H       1149   3-07-88   5:10a
  6839.  SEARCH   H       1137   3-07-88   5:10a
  6840.  SETJMP   H        915   3-07-88   5:10a
  6841.  SHARE    H        554   3-07-88   5:10a
  6842.  SIGNAL   H       1941   3-07-88   5:10a
  6843.  STDARG   H        622   3-07-88   5:10a
  6844.  STDDEF   H       1217   3-07-88   5:10a
  6845.  STDIO    H       5046   3-07-88   5:10a
  6846.  STDLIB   H       5335   3-07-88   5:10a
  6847.  STRING   H       2629   3-07-88   5:10a
  6848.  TIME     H       2693   3-07-88   5:10a
  6849.  VARARGS  H        650   3-07-88   5:10a
  6850.  PROCESS  H       2370   3-07-88   5:10a
  6851.  OS2      H        707   3-07-88   5:10a
  6852.  OS2DEF   H       5891   3-07-88   5:10a
  6853.  BSE      H       1139   3-07-88   5:10a
  6854.  BSEDOS   H      17730   3-07-88   5:10a
  6855.  BSEERR   H      20940   3-07-88   5:10a
  6856.  BSESUB   H      11512   3-07-88   5:10a
  6857.       35 File(s)   242688 bytes free
  6858.  
  6859.   Volume in drive B has no label.
  6860.   Directory of B:\INCLMT\SYS
  6861.  
  6862.  .            <DIR>      3-07-88   5:10a
  6863.  ..           <DIR>      3-07-88   5:10a
  6864.  LOCKING  H        573   3-07-88   5:10a
  6865.  STAT     H       1517   3-07-88   5:10a
  6866.  TIMEB    H        852   3-07-88   5:10a
  6867.  TYPES    H        849   3-07-88   5:10a
  6868.  UTIME    H       1073   3-07-88   5:10a
  6869.       7 File(s)   242688 bytes free
  6870.  
  6871.  :::::::::::::::::::::::::::::::::::::::
  6872.  
  6873.  (Disk 9 of 10)  -  MS OS/2 Libraries 1
  6874.  
  6875.   Volume in drive B has no label.
  6876.   Directory of B:\
  6877.  
  6878.  SLIBCP   LIB   119999   3-07-88   5:10a
  6879.  MLIBCP   LIB   121535   3-07-88   5:10a
  6880.  CLIBCP   LIB   129257   3-07-88   5:10a
  6881.  LLIBCP   LIB   130793   3-07-88   5:10a
  6882.  APILMR   OBJ      105   3-07-88   5:10a
  6883.  API      LIB    81408   3-07-88   5:10a
  6884.       6 File(s)   143360 bytes free
  6885.  
  6886.  :::::::::::::::::::::::::::::::::::::::
  6887.  
  6888.  (Disk 10 of 10)  -  MS OS/2 Libraries 2
  6889.  
  6890.   Volume in drive B has no label.
  6891.   Directory of B:\
  6892.  
  6893.  EXAMPLE      <DIR>      3-07-88   5:10a
  6894.  CDLLSUPP LIB     9475   3-07-88   5:10a
  6895.  LLIBCDLL LIB   178143   3-07-88   5:10a
  6896.  LLIBCMT  LIB   198913   3-07-88   5:10a
  6897.  CDLLOBJS LIB   203063   3-07-88   5:10a
  6898.  CDLLOBJS DEF     4397   3-07-88   5:10a
  6899.  CDLLOBJS CMD     2048   3-07-88   5:10a
  6900.  CRTEXE   OBJ     1089   3-07-88   5:10a
  6901.  CRTDLL   OBJ      577   3-07-88   5:10a
  6902.  CRTLIB   OBJ     1177   3-07-88   5:10a
  6903.       10 File(s)   93184 bytes free
  6904.  
  6905.   Volume in drive B has no label.
  6906.   Directory of B:\EXAMPLE
  6907.  
  6908.  .            <DIR>      3-07-88   5:10a
  6909.  ..           <DIR>      3-07-88   5:10a
  6910.  MHELLO   C       2990   3-07-88   5:10a
  6911.  MKMHELLO CMD      433   3-07-88   5:10a
  6912.  STMAIN   C        825   3-07-88   5:10a
  6913.  STMAIN   DEF       41   3-07-88   5:10a
  6914.  STDLL    C        393   3-07-88   5:10a
  6915.  STDLL    DEF      124   3-07-88   5:10a
  6916.  MKSTDLL  CMD      714   3-07-88   5:10a
  6917.  MTMAIN   C        735   3-07-88   5:10a
  6918.  MTMAIN   DEF       41   3-07-88   5:10a
  6919.  MTDLL    C        393   3-07-88   5:10a
  6920.  MTDLL    DEF      124   3-07-88   5:10a
  6921.  MKMTDLL  CMD     1587   3-07-88   5:10a
  6922.  SNAP     C      13083   3-07-88   5:10a
  6923.  MAKESNAP CMD     2148   3-07-88   5:10a
  6924.       16 File(s)   93184 bytes free
  6925.  
  6926.  
  6927.  143. Quick Reference Documentation Error with _setbkcolor
  6928.  
  6929.  Product Version(s): 5.00 5.10 | 5.10
  6930.  Operating System:   MS-DOS    | OS/2
  6931.  Flags: ENDUSER | docerr
  6932.  Last Modified: 23-SEP-1988    ArticleIdent: Q35805
  6933.  
  6934.  In the Library Routines section of the C Versions 5.00 and 5.10
  6935.  "Microsoft Quick Reference Guide," the function _setbkcolor has the
  6936.  incorrect argument type. Instead of a short type argument, the
  6937.  argument should be a long type.
  6938.  
  6939.  
  6940.  144. Sample Pascal Program Documentation Error: function Fact
  6941.  
  6942.  Product Version(s): 5.00 5.10 | 5.10
  6943.  Operating System:   MS-DOS    | OS/2
  6944.  Flags: ENDUSER | h_masm S_PASCAL h_fortran
  6945.  Last Modified: 23-SEP-1988    ArticleIdent: Q35812
  6946.  
  6947.  In the Microsoft Mixed-Language Programming Guide in section 5.4.2 on
  6948.  Page 64, the Pascal function declaration is stated as follows:
  6949.  
  6950.  function Fact (n: integer) [C]; extern;
  6951.  
  6952.  The Pascal function declaration should be the following:
  6953.  
  6954.  function Fact (n: integer) : integer [C]; extern;
  6955.  
  6956.  
  6957.  
  6958.  145. Source Not Available for MS Binary to IEEE Conversion
  6959.  
  6960.  Product Version(s): 5.00 5.10 | 5.00 5.10
  6961.  Operating System:   MS-DOS    | OS/2
  6962.  Flags: ENDUSER   |
  6963.  Last Modified: 12-OCT-1988    ArticleIdent: Q35988
  6964.  
  6965.  The following functions are not included in the C Run-Time Library
  6966.  Source Routines:
  6967.  
  6968.  dieeetomsbin
  6969.  dmsbintoieee
  6970.  fieeetomsbin
  6971.  fmsbintoieee
  6972.  
  6973.  These functions are incorrectly listed in a flier called "Microsoft C
  6974.  Run-Time Library Source Runtime" as included in the product.
  6975.  
  6976.  
  6977.  146. C: Automatic Casting from Near Pointer to Far Pointer
  6978.  
  6979.  Product Version(s): 5.10   | 5.10
  6980.  Operating System:   MS-DOS | OS/2
  6981.  Flags: ENDUSER |
  6982.  Last Modified: 17-MAY-1989    ArticleIdent: Q43486
  6983.  
  6984.  In Microsoft C, the automatic type casting from a near pointer to a
  6985.  far pointer that is performed by the compiler will make the segment
  6986.  address of the resulting pointer the same as that of DGroup. In those
  6987.  cases, no explicit type casting is needed.
  6988.  
  6989.  Two of the cases of the automatic casting are shown in the following
  6990.  sample program:
  6991.  
  6992.  #include <malloc.h>
  6993.  
  6994.  void foo (char far *) ;
  6995.  void main (void)
  6996.  {
  6997.  char far *lpChar ;
  6998.  char * npChar ;
  6999.  lpChar = malloc( 100 );   /* malloc is mapped to _nmalloc,
  7000.                            ** and returns near pointer, automatic type
  7001.                            ** casting is performed with assignment */
  7002.  
  7003.  foo( npChar ) ;           /* npChar is converted to a far pointer
  7004.                            ** with the segment address to be DS */
  7005.  }
  7006.  
  7007.  void foo (char far * p)
  7008.  {
  7009.  }
  7010.  
  7011.  
  7012.  147. IEEE Floating-Point Representation and MS languages
  7013.  
  7014.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  7015.  Operating System:   MS-DOS              | OS/2
  7016.  Flags: ENDUSER | s_pascal h_fortran h_masm b_quickbas
  7017.  Last Modified:  8-MAR-1989    ArticleIdent: Q36068
  7018.  
  7019.  The following information discusses how real*4 (single precision) and
  7020.  real*8 (double precision) numbers are stored internally by Microsoft
  7021.  languages that use the IEEE floating-point format. The Microsoft
  7022.  Binary Format (MBF) for floating-point storage, which is used by the
  7023.  BASIC interpreter for MS-DOS and by QuickBASIC up through Versions
  7024.  3.x, is NOT discussed in this article.
  7025.  
  7026.  This information applies to all versions of Microsoft languages that
  7027.  use IEEE floating-point format, including the following:
  7028.  
  7029.  1. C Versions 3.00, 4.00, 5.00, and 5.10
  7030.  
  7031.  2. FORTRAN Versions 3.1x, 3.20, 3.30, 4.0x, and 4.10
  7032.  
  7033.  3. MASM Versions 1.25, 1.27, 3.0x, 4.00, 5.00, and 5.10
  7034.  
  7035.  4. Pascal Versions 3.1x, 3.20, 3.30, 3.31, 3.32, and 4.00
  7036.  
  7037.  5. The coprocessor version of QuickBASIC Version 3.00 (QB87.EXE), and
  7038.     QuickBASIC Versions 4.00, 4.00b, and 4.50
  7039.  
  7040.  There are three internal varieties of real numbers. Microsoft is
  7041.  consistent with the IEEE numeric standards. Real*4 and real*8 are used
  7042.  in all of our languages. Real*10 is used only with MASM. Real*10 is
  7043.  also what any 8087, 80287, or 80387 coprocessor and the emulator math
  7044.  package use when performing floating-point calculations.
  7045.  
  7046.  In FORTRAN, real*4 is declared using the words "REAL" or "REAL*4."
  7047.  The words "DOUBLE PRECISION" or "REAL*8" are used to declare a real*8
  7048.  number.
  7049.  
  7050.  In C, real*4 is declared using the word "float." Real*8 is declared
  7051.  using the word "double" or "long double."
  7052.  
  7053.  In Pascal, real*4 is declared using the word "real4," and real*8 is
  7054.  declared using the word "real8."  The word "real" defaults to real*4,
  7055.  but this can be changed to real*8 with the $real:8 metacommand.
  7056.  
  7057.  In MASM, real*4 is declared with the "DD" directive, real*8 is
  7058.  declared with the "DQ" directive, and real*10 is declared with the
  7059.  "DT" directive.
  7060.  
  7061.  In QuickBASIC, the default variable type is real*4. Variables that
  7062.  have an exclamation point ("!") as their last character are also
  7063.  real*4. Variables that have a cross-hatch (also called pound-sign,
  7064.  "#" as the last character of its name are double precision (real*8).
  7065.  The DEFSNG and DEFDBL statements can be used to declare that variables
  7066.  whose names begin with certain letters and are of a certain type.
  7067.  These types can also be declared with the keywords SINGLE and DOUBLE.
  7068.  
  7069.  The values are stored as follows:
  7070.  
  7071.  real*4  sign bit, 8  bit exponent, 23 bit mantissa
  7072.  real*8  sign bit, 11 bit exponent, 52 bit mantissa
  7073.  real*10 sign bit, 15 bit exponent, 64 bit mantissa
  7074.  
  7075.  In real*4 and real*8 formats, there is an assumed leading one in the
  7076.  mantissa that is not stored in memory, so the mantissas are actually
  7077.  24 or 53 bits, even though only 23 or 52 bits are stored.  The
  7078.  real*10 format stores actually stores this bit.
  7079.  
  7080.  The exponents are biased by half of their possible value. This means
  7081.  you subtract this bias from the stored exponent to get the actual
  7082.  exponent. If the stored exponent is less than the bias, it is actually
  7083.  a negative exponent.
  7084.  
  7085.  The exponents are biased as follows:
  7086.  
  7087.  8-bit  (real*4)  exponents are biased by 127
  7088.  11-bit (real*8)  exponents are biased by 1023
  7089.  15-bit (real*10) exponents are biased by 16383
  7090.  
  7091.  These exponents are not powers of ten; they are powers of two, i.e.,
  7092.  8-bit stored exponents can be up to 127. 2**127 is roughly equivalent
  7093.  to 10**38, which is the actual limit of real*4.
  7094.  
  7095.  The mantissa is stored as a binary fraction of the form 1.XXX... .
  7096.  This fraction has a value greater than or equal to 1 and less than 2.
  7097.  Note that real numbers are always stored in normalized form, i.e., the
  7098.  mantissa is left-shifted such that the high-order bit of the mantissa
  7099.  is always one. Because this bit is always one, it is assumed (not
  7100.  stored) in the real*4 and real*8 formats. The binary (not decimal)
  7101.  point is assumed to be just to the right of the leading one.
  7102.  
  7103.  The format, then, for the various sizes is as follows:
  7104.  
  7105.             BYTE 1    BYTE 2    BYTE 3    BYTE 4   ...  BYTE n
  7106.  real*4    SXXX XXXX XMMM MMMM MMMM MMMM MMMM MMMM
  7107.  real*8    SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM
  7108.  real*10   SXXX XXXX XXXX XXXX 1MMM MMMM MMMM MMMM ... MMMM MMMM
  7109.  
  7110.  S represents the sign bit, the X's are the exponent bits, and the M's
  7111.  are the mantissa bits. Note that the leftmost one is assumed in real*4
  7112.  and real*8 formats, but present as "1" in BYTE 3 of the real*10
  7113.  format.
  7114.  
  7115.  To shift the binary point properly, you first un-bias the exponent and
  7116.  then move the binary point to the right or left the appropriate number
  7117.  of bits.
  7118.  
  7119.  The following are some examples in real*4 format:
  7120.  
  7121.                      SXXX XXXX XMMM MMMM ... MMMM MMMM
  7122.  2   =  1  * 2**1  = 0100 0000 0000 0000 ... 0000 0000 = 4000 0000
  7123.      Note the sign bit is zero, and the stored exponent is 128, or
  7124.      100 0000 0 in binary, which is 127 plus 1.  The stored mantissa
  7125.      is (1.) 000 0000 ... 0000 0000, which has an implied leading
  7126.      1 and binary point, so the actual mantissa is one.
  7127.  -2  = -1  * 2**1  = 1100 0000 0000 0000 ... 0000 0000 = C000 0000
  7128.      Same as +2 except that the sign bit is set.  This is true for
  7129.          all IEEE format floating-point numbers.
  7130.   4  =  1  * 2**2  = 0100 0000 1000 0000 ... 0000 0000 = 4080 0000
  7131.      Same mantissa, exponent increases by one (biased value is
  7132.      129, or 100 0000 1 in binary.
  7133.   6  = 1.5 * 2**2  = 0100 0000 1100 0000 ... 0000 0000 = 40C0 0000
  7134.      Same exponent, mantissa is larger by half--it's
  7135.      (1.) 100 0000 ... 0000 0000, which, since this is a binary
  7136.      fraction, is 1 1/2 (the values of the fractional digits are
  7137.      1/2, 1/4, 1/8, etc.).
  7138.   1  = 1   * 2**0  = 0011 1111 1000 0000 ... 0000 0000 = 3F80 0000
  7139.      Same exponent as other powers of two, mantissa is one less
  7140.      than two at 127, or 011 1111 1 in binary.
  7141.  .75 = 1.5 * 2**-1 = 0011 1111 0100 0000 ... 0000 0000 = 3F40 0000
  7142.      The biased exponent is 126, 011 1111 0 in binary, and the
  7143.      mantissa is (1.) 100 0000 ... 0000 0000, which is 1 1/2.
  7144.  2.5 = 1.25 * 2**1 = 0100 0000 0010 0000 ... 0000 0000 = 4020 0000
  7145.      Exactly the same as two except that the bit which represents
  7146.      1/4 is set in the mantissa.
  7147.  0.1 = 1.6 * 2**-4 = 0011 1101 1100 1100 ... 1100 1101 = 3DCC CCCD
  7148.      1/10 is a repeating fraction in binary. The mantissa is
  7149.      just shy of 1.6, and the biased exponent says that 1.6 is to
  7150.      be divided by 16 (it is 011 1101 1 in binary, which is 123 in
  7151.      decimal). The true exponent is 123 - 127 = -4, which means
  7152.      that the factor by which to multiply is 2**-4 = 1/16. Note
  7153.      that the stored mantissa is rounded up in the last bit--an
  7154.      attempt to represent the unrepresentable number as accuartely
  7155.      as possible. (The reason that 1/10 and 1/100 are not exactly
  7156.      representable in binary similar to the reason that 1/3 is not
  7157.      exactly representable in decimal.)
  7158.   0  = 1.0 * 2**-128 = all zero's--a special case.
  7159.  
  7160.  
  7161.  148. Different Results between Alternate and Coprocessor/Emulator Math
  7162.  
  7163.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  7164.  Operating System:   MS-DOS              | OS/2
  7165.  Flags: ENDUSER | s_pascal h_fortran h_masm
  7166.  Last Modified: 12-OCT-1988    ArticleIdent: Q36069
  7167.  
  7168.  There may be differences between the floating point values you get
  7169.  when using coprocessor/emulator math and the alternate math packages.
  7170.  
  7171.  This behavior applies to C Versions 3.00, 4.00, 5.00, and 5.01, Pascal
  7172.  Versions 3.1x, 3.20, 3.30, 3.31, 3.32, and 4.00, FORTRAN Versions
  7173.  3.1x, 3.20, 3.30, 3.31, 4.0x, and 4.10, and MASM Versions 1.25, 1.27,
  7174.  3.0x, 4.00, 5.00, and 5.10.
  7175.  
  7176.  When you do any floating point arithmetic with the coprocessor all
  7177.  values are pushed onto the coprocessor stack. The coprocessor stack
  7178.  only holds 10-byte reals. This means that all real*4 and/or real*8
  7179.  (real/double) are expanded to 10-byte reals, then all of the
  7180.  arithmetic is done on these 10-byte reals. The emulator package does
  7181.  this same expansion. The results of floating point calculations are
  7182.  then rounded back down to real*4 or real*8 format.
  7183.  
  7184.  Alternate math calculations are performed using real*4 or real*8
  7185.  format which can result in less precision than that available with
  7186.  coprocessor/emulator math.
  7187.  
  7188.  
  7189.  149. Share Problems Using sopen and Incorrect oflag
  7190.  
  7191.  Product Version(s): 5.00 5.10
  7192.  Operating System:   MS-DOS
  7193.  Flags: ENDUSER | docerr
  7194.  Last Modified: 12-OCT-1988    ArticleIdent: Q36611
  7195.  
  7196.  The "important" note on Page 550 of the "Microsoft Optimizing 5.1
  7197.  Compiler Run-Time Library Reference" manual has an error in the second
  7198.  condition listed as causing problems when opening a new file with the
  7199.  sopen function under DOS Versions 3.00, 3.10, or 3.20 with SHARE
  7200.  installed.
  7201.  
  7202.  "With oflag set to any combination that includes O_FLAG..." is
  7203.  incorrect. There is no O_FLAG setting available. The oflag setting
  7204.  should be O_CREAT | O_RDWR. This oflag setting with pmode set to
  7205.  S_IREAD requires that shflag be set to SH_COMPAT to avoid problems
  7206.  with the new file created by sopen.
  7207.  
  7208.  The problems that can occur when the wrong sopen options are used
  7209.  include not opening the new file, or opening the new file but not
  7210.  being able to write to it resulting in a file of zero length.
  7211.  
  7212.  These problems may also occur in DOS Version 3.30.
  7213.  
  7214.  
  7215.  150. Filename from tmpnam Has Prefix from P_tmpdir
  7216.  
  7217.  Product Version(s): 4.00 5.00 5.10  | 5.10
  7218.  Operating System:   MS-DOS          | OS/2
  7219.  Flags: ENDUSER |
  7220.  Last Modified: 18-OCT-1988    ArticleIdent: Q36675
  7221.  
  7222.  The tmpnam function generates a temporary filename that can be used as
  7223.  a temporary file. The character string that tmpnam creates consists of
  7224.  the path prefix defined by the P_tmpdir entry in stdio.h, followed by
  7225.  a sequence consisting of the digit characters "0" through "9".
  7226.  
  7227.  This information is in the "Microsoft C 5.1 Optimizing Compiler
  7228.  Run-Time Library Reference" manual on Page 611. The "Microsoft C 4.00
  7229.  Run-Time Library Reference" manual does not describe this naming
  7230.  behavior.
  7231.  
  7232.  In Version 5.00 and 5.10, the P_tmpdir entry is defined in stdio.h
  7233.  as follows:
  7234.  
  7235.  #define P_tmpdir "\\"
  7236.  
  7237.  In Version 4.00, the P_tmpdir entry is defined in stdio.h as follows:
  7238.  
  7239.  #define P_tmpdir "\\TMP"
  7240.  
  7241.  Thus, a string for a temporary filename created under Version 4.00
  7242.  will have the form \TMP\x (where x is the generated number), and it
  7243.  will be necessary to have a TMP subdirectory.
  7244.  
  7245.  
  7246.  151. Warning C4000 Unknown Warning
  7247.  
  7248.  Product Version(s): 5.00 5.10 | 5.10
  7249.  Operating System:   MS-DOS    | OS/2
  7250.  Flags: ENDUSER | s_quickc s_error
  7251.  Last Modified: 14-NOV-1988    ArticleIdent: Q36695
  7252.  
  7253.  This information is from section D.1.3 (Page 340) of the "Microsoft
  7254.  QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
  7255.  "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7256.  5.10.
  7257.  
  7258.  The messages listed in this section indicate potential problems but do
  7259.  not hinder compilation and linking. The number in parentheses at the
  7260.  end of an error-message description gives the minimum warning level
  7261.  that must be set for the message to appear.
  7262.  
  7263.  The following is the warning:
  7264.  
  7265.  C4000    Unknown Warning
  7266.           The compiler detected an unknown error condition.
  7267.  
  7268.           Please report this condition to Microsoft Corporation, using
  7269.           the Product Assistance Request form at the back of this
  7270.           manual.
  7271.  
  7272.  The occurance of this warning indicates a problem with the compiler.
  7273.  Please include the smallest possible example of source code which
  7274.  demonstrates the problem when sending the Software Problem Report to
  7275.  Microsoft.
  7276.  
  7277.  
  7278.  152. Warning C4017 Cast of int Expression to far Pointer
  7279.  
  7280.  Product Version(s): 5.00 5.10 | 5.10
  7281.  Operating System:   MS-DOS    | OS/2
  7282.  Flags: ENDUSER | s_quickc s_error
  7283.  Last Modified: 14-NOV-1988    ArticleIdent: Q36706
  7284.  
  7285.  This information is from section D.1.3 (Page 340) of the "Microsoft
  7286.  QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
  7287.  "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7288.  5.10.
  7289.  
  7290.  This message indicates potential problems but does not hinder
  7291.  compilation and linking. The number in parentheses at the end of a
  7292.  warning-message description gives the minimum warning level that must
  7293.  be set for the message to appear.
  7294.  
  7295.  The following is the warning:
  7296.  
  7297.  C4017       cast of int expression to far pointer
  7298.  
  7299.              A far pointer represents a full segmented address.  On
  7300.              an 8086/8088 processor, casting an 'int' value to a
  7301.              far pointer may produce an address with a meaningless
  7302.              segment value.  (1)
  7303.  
  7304.  A possible cause for this warning is that a function that returns a far
  7305.  pointer was not prototyped and the compiler assumed the return type of
  7306.  the function to be "int" instead of a far pointer as was actually
  7307.  intended.
  7308.  
  7309.  The followin is a code example:
  7310.  
  7311.  main()
  7312.  {
  7313.    char far *address ;
  7314.  
  7315.    address = foo () ;
  7316.  }
  7317.  
  7318.  Since foo was not prototyped, the compiler will assume that foo
  7319.  returns an integer. If the warning level is set at 2, this code would
  7320.  receive the warning C4016 "foo : no function return type" (if the
  7321.  warning level were set to 1).
  7322.  
  7323.  
  7324.  153. Warning C4028 Parameter 'n' Declaration Different
  7325.  
  7326.  Product Version(s): 5.00 5.10 | 5.10
  7327.  Operating System:   MS-DOS    | OS/2
  7328.  Flags: ENDUSER | s_quickc s_error
  7329.  Last Modified: 14-NOV-1988    ArticleIdent: Q36710
  7330.  
  7331.  This information is from section D.1.3 (Page 340) of the "Microsoft
  7332.  QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
  7333.  "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7334.  5.10.
  7335.  
  7336.  This message indicates potential problems but does not hinder
  7337.  compilation and linking. The number in parentheses at the end of a
  7338.  warning-message description gives the minimum warning level that must
  7339.  be set for the message to appear.
  7340.  
  7341.  The following is the warning:
  7342.  
  7343.  C4028       parameter 'n' declaration different
  7344.  
  7345.              The type of the given parameter did not agree with the
  7346.              corresponding type in the argument-type list or with
  7347.              the corresponding formal parameter. (1)
  7348.  
  7349.  Note: this message may appear when it should actually have produced
  7350.  the warning C4074 if an ellipsis is used in the prototype.
  7351.  
  7352.  The call of the function gave a parameter type that did not match up
  7353.  with prototype and function definition, as in the following code
  7354.  fragment:
  7355.  
  7356.  void foo (int) ;
  7357.  
  7358.  main ()
  7359.  {
  7360.    float fp ;
  7361.    foo (fp) ;
  7362.  }
  7363.  
  7364.  void foo (int)
  7365.  {
  7366.  }
  7367.  
  7368.  
  7369.  154. Warning C4037 'identifier' : Formal Parameters Ignored
  7370.  
  7371.  Product Version(s): 5.00 5.10 | 5.10
  7372.  Operating System:   MS-DOS    | OS/2
  7373.  Flags: ENDUSER | s_quickc s_error
  7374.  Last Modified: 14-NOV-1988    ArticleIdent: Q36722
  7375.  
  7376.  This information is from section D.1.3 (Page 340) of the "Microsoft
  7377.  QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
  7378.  Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7379.  5.10.
  7380.  
  7381.  This message indicates potential problems but does not hinder
  7382.  compilation and linking. The number in parentheses at the end of a
  7383.  warning-message description gives the minimum warning level that must
  7384.  be set for the message to appear.
  7385.  
  7386.  The following is the warning:
  7387.  
  7388.  C4037       'identifier' : formal parameters ignored
  7389.  
  7390.              No storage class or type name appeared before the
  7391.              declarators of formal parameters in a function
  7392.              declaration, as in the following example:
  7393.  
  7394.              int *f(a,b,c);
  7395.  
  7396.              The formal parameters are ignored. (1)
  7397.  
  7398.  The prototype for this function, f, did not declare the types of
  7399.  arguments that the function receives. You could correct the above
  7400.  example as follows:
  7401.  
  7402.  int *f (int a, int b, int c) ;
  7403.  
  7404.  
  7405.  155. Warning C4040 near/far/huge on 'identifier' Ignored
  7406.  
  7407.  Product Version(s): 5.00 5.10 | 5.10
  7408.  Operating System:   MS-DOS    | OS/2
  7409.  Flags: ENDUSER | s_quickc s_error
  7410.  Last Modified: 14-NOV-1988    ArticleIdent: Q36725
  7411.  
  7412.  This information is from section D.1.3 (Page 340) of the "Microsoft
  7413.  QuickC Programmer's Guide and section E.3.3 (Page 269) of the
  7414.  "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7415.  5.10.
  7416.  
  7417.  This message indicates potential problems but does not hinder
  7418.  compilation and linking. The number in parentheses at the end of a
  7419.  warning-message description gives the minimum warning level that must
  7420.  be set for the message to appear.
  7421.  
  7422.  The following is the warning:
  7423.  
  7424.  C4040       near/far/huge on 'identifier' ignored
  7425.  
  7426.              The 'near' or 'far' keyword has no effect in the
  7427.              declaration of the given identifier and is ignored.
  7428.  
  7429.  You cannot declare an array to be huge if it is declared within a
  7430.  function because this array will reside on the stack that is limited
  7431.  to the default data segment. You can move the declaration of the array
  7432.  with the huge keyword outside of all functions, use the "static" or
  7433.  "extern" keywords to move the array into a far data segment, or use a
  7434.  huge or far pointer.
  7435.  
  7436.  QuickC Versions 1.00 and 1.01 do not support the huge keyword or the
  7437.  huge-memory model.
  7438.  
  7439.  
  7440.  
  7441.  156. Warning C4047 'operator': Different Levels of Indirection
  7442.  
  7443.  Product Version(s): 5.00 5.10 | 5.10
  7444.  Operating System:   MS-DOS    | OS/2
  7445.  Flags: ENDUSER | s_quickc s_error
  7446.  Last Modified: 14-NOV-1988    ArticleIdent: Q36729
  7447.  
  7448.  This information is from section D.1.3 (Page 340) of the "Microsoft
  7449.  QuickC Programmer's Guide" and section E.3.3 (Page 269) of the
  7450.  "Microsoft C Optimizing Compiler User's Guide" for Version 5.00 and
  7451.  5.10.
  7452.  
  7453.  This message indicates potential problems but does not hinder
  7454.  compilation and linking. The number in parentheses at the end of a
  7455.  warning-message description gives the minimum warning level that must
  7456.  be set for the message to appear.
  7457.  
  7458.  The following is the warning message:
  7459.  
  7460.  C4047       'operator' : different levels of indirection
  7461.  
  7462.              An expression involving the specified operator had
  7463.              inconsistent levels of indirection. (1)
  7464.  
  7465.  The following example illustrates this condition:
  7466.  
  7467.              char **p ;
  7468.              char  *q ;
  7469.              .
  7470.              .
  7471.              p = q ;
  7472.  
  7473.  You will commonly get this warning if you do not cast MALLOC() to your
  7474.  pointer type. The following code fragment will produce the C4047
  7475.  message:
  7476.              char *string ;
  7477.              string = malloc (5) ;
  7478.  
  7479.  To eliminate this warning message in this example, cast MALLOC() as
  7480.  follows:
  7481.              string = (char *) malloc (5) ;
  7482.  
  7483.  This is a result of the fact that MALLOC()'s default return type is
  7484.  "void *".
  7485.  
  7486.  
  7487.  157. C2086 Error When Compiling with /Oi and #include <mt\math.h>
  7488.  
  7489.  Product Version(s): 5.10
  7490.  Operating System:   OS/2
  7491.  Flags: ENDUSER |
  7492.  Last Modified: 16-JAN-1990    ArticleIdent: Q36782
  7493.  
  7494.  When using the multithreaded version of <math.h>, error C2086
  7495.  "identifier redefinition" occurs if -Oi (or -Ox) intrinsic
  7496.  optimization is enabled. The cause of the error is the fact that the
  7497.  compiler has built-in prototypes for intrinsic functions. Because
  7498.  <mt\math.h> declares these functions differently, the C2086 error is
  7499.  generated.
  7500.  
  7501.  This conflict arises for the following floating-point routines:
  7502.  
  7503.     acos  asin  atan  atan2  cos  exp  fabs  fmod  log  log10  pow
  7504.     sin   sinh  sqrt  tan    tanh
  7505.  
  7506.  The conflict occurs because the compiler has built-in function
  7507.  prototypes for routines for which it is generating intrinsics. When
  7508.  you compile with the normal include files, the compiler's internal
  7509.  prototype is the same as the one in <math.h>, so there is no conflict.
  7510.  However, when you use <mt\math.h>, the prototypes are changed from
  7511.  "_CDECL" to "far pascal", which causes the redefinition error.
  7512.  
  7513.  One workaround is to use the following
  7514.  
  7515.     #pragma function ({func1} {func2} {etc})
  7516.  
  7517.  at the start of the module to force functions to be used instead of
  7518.  intrinsics. This will also work if you are using the alternate math
  7519.  library with multithreaded and/or DLL modules and the link fails with
  7520.  unresolved externals.
  7521.  
  7522.  A second workaround to this conflict is to use the C preprocessor's
  7523.  conditional-compilation facility, as in the following fragment of
  7524.  <mt\math.h>:
  7525.  
  7526.  ----------------------------------------------------------------------
  7527.      last part of <mt\math.h>
  7528.  ----------------------------------------------------------------------
  7529.  
  7530.  /* function prototypes */
  7531.  
  7532.  #ifndef INTRINSICS    /* this is the modification */
  7533.  
  7534.  double far pascal acos(double);
  7535.  double far pascal asin(double);
  7536.  double far pascal atan(double);
  7537.  double far pascal atan2(double, double);
  7538.  double far pascal cos(double);
  7539.  double far pascal cosh(double);
  7540.  double far pascal exp(double);
  7541.  double far pascal fabs(double);
  7542.  double far pascal fmod(double, double);
  7543.  double far pascal log(double);
  7544.  double far pascal log10(double);
  7545.  double far pascal pow(double, double);
  7546.  double far pascal sin(double);
  7547.  double far pascal sinh(double);
  7548.  double far pascal sqrt(double);
  7549.  double far pascal tan(double);
  7550.  double far pascal tanh(double);
  7551.  
  7552.  #endif  /* INTRINSICS; end of modification */
  7553.  
  7554.  int    far _CDECL abs(int);
  7555.  double far pascal atof(const char far *);
  7556.  double far pascal cabs(struct complex);
  7557.  double far pascal ceil(double);
  7558.  int    far _CDECL dieeetomsbin(double far *, double far *);
  7559.  int    far _CDECL dmsbintoieee(double far *, double far *);
  7560.  int    far _CDECL fieeetomsbin(float far *, float far *);
  7561.  double far pascal floor(double);
  7562.  int    far _CDECL fmsbintoieee(float far *, float far *);
  7563.  double far pascal frexp(double, int far *);
  7564.  double far pascal hypot(double, double);
  7565.  double far pascal j0(double);
  7566.  double far pascal j1(double);
  7567.  double far pascal jn(int, double);
  7568.  long   far _CDECL labs(long);
  7569.  double far pascal ldexp(double, int);
  7570.  int    far _CDECL matherr(struct exception far *);
  7571.  double far pascal modf(double, double far *);
  7572.  double far pascal y0(double);
  7573.  double far pascal y1(double);
  7574.  double far pascal yn(int, double);
  7575.  
  7576.  In this version of <mt\math.h>, the intrinsic math routines have been
  7577.  pulled out of the main block of function prototypes and conditionally
  7578.  compiled; the preprocessor will include them only if the symbol
  7579.  "INTRINSICS" is not defined. This way, under normal circumstances,
  7580.  nothing is different; when you #include <mt\math.h>, all the
  7581.  prototypes are included. But when you want to optimize with /Ox or
  7582.  /Oi, you can use the following command-line option so that the
  7583.  preprocessor will remove those prototypes from the compilation:
  7584.  
  7585.  cl  ... /D INTRINSICS ...
  7586.  
  7587.  
  7588.  158. Microsoft OS/2 Languages Use Virtual Memory
  7589.  
  7590.  Product Version(s): 5.10
  7591.  Operating System:   OS/2
  7592.  Flags: ENDUSER | h_fortran 4.10 h_masm 5.10 S_PASCAL 4.00
  7593.  Last Modified: 18-OCT-1988    ArticleIdent: Q36791
  7594.  
  7595.  Question:
  7596.  
  7597.  Will Microsoft's OS/2 languages use virtual memory under OS/2?
  7598.  
  7599.  Response:
  7600.  
  7601.  OS/2 will make use of virtual memory if memman=MOVE is set in the
  7602.  CONFIG.OS2 or CONFIG.SYS file, physical RAM becomes full, and there is
  7603.  enough free disk space to swap to. OS/2 is generally not dependent on
  7604.  the nature of the application for using virtual memory, except for
  7605.  device drivers that may require fixed segments of physical RAM.
  7606.  
  7607.  
  7608.  159. Error C2106 when Assigning a String Literal to a char Array
  7609.  
  7610.  Product Version(s): 5.00 5.10 | 5.10
  7611.  Operating System:   MS-DOS    | OS/2
  7612.  Flags: ENDUSER | S_QuickC
  7613.  Last Modified: 18-OCT-1988    ArticleIdent: Q36870
  7614.  
  7615.  A common error in C is to attempt to fill a character array, defined
  7616.  as char arrayname[somelength], with a string constant by use of the
  7617.  simple-assignment operator (i.e., the equal sign, = ). This error
  7618.  causes the compiler error "error C2106: '=' : left operand must be
  7619.  lvalue."
  7620.  
  7621.  Example 1, which does not compile and causes this error, follows
  7622.  immediately. An extended example (Example 2), which compiles and runs
  7623.  and demonstrates some concepts, is given below along with its output.
  7624.  
  7625.  The following is Example 1:
  7626.  
  7627.  /* This code gives compiler error C2106. */
  7628.  #include <string.h>
  7629.  char string1[10];
  7630.  
  7631.  void main(void);
  7632.  void main(void)
  7633.  {
  7634.          string1 = "String1";
  7635.  }
  7636.  
  7637.  As another way to fill an array, non-auto (i.e. global) char arrays
  7638.  and char pointers (starting with C Version 5.00) may be initialized
  7639.  when declared as in the following two lines:
  7640.  
  7641.  char string1[10] = "String1";
  7642.  char *string2 = "String2";
  7643.  
  7644.  The following is Example 2:
  7645.  
  7646.  /* This example demonstrates some string usage principles. */
  7647.  #include <stdio.h>
  7648.  #include <string.h>
  7649.  #include <malloc.h>
  7650.  
  7651.  char string1[40];       /* string1 is an array of char  */
  7652.  char *string2;          /* string2 is a pointer to char */
  7653.          /* Important: Know when to malloc space for string2. */
  7654.  
  7655.  void main(void);
  7656.  void main(void)
  7657.  {
  7658.              /* This shows the correct way to achieve the   */
  7659.              /* assignment intended by string1 = "String1"; */
  7660.          strcpy(string1, "Contents of string1");
  7661.          printf("1:%s\n\n", string1);
  7662.  
  7663.              /* These two assignments show two ways to     */
  7664.              /* use a char pointer with a string literal.  */
  7665.          string2 = "Contents of string2"; /* point to the literal */
  7666.          printf("2:%s\n", string2);
  7667.              /* allocate memory for char *string2 to point at */
  7668.          string2 = (char *) malloc(sizeof(string1));
  7669.          strcpy(string2, "Contents of string2, again");
  7670.          printf("3:%s\n\n", string2);
  7671.          free(string2);
  7672.  
  7673.          /* This shows a failed attempt to fill a char  */
  7674.              /* array by assignment through a char pointer. */
  7675.          string2 = string1;
  7676.          string2 = "Contents of string2, but not string1";
  7677.          printf("4:%s\n", string1);
  7678.          printf("5:%s\n\n", string2);
  7679.  
  7680.              /* This shows how correctly to use a pointer   */
  7681.              /* to fill a char array with a string literal. */
  7682.          string2 = string1;
  7683.          strcpy(string2, "Contents of string2, and also string1");
  7684.          printf("6:%s\n", string1);
  7685.          printf("7:%s\n\n", string2);
  7686.  }
  7687.  
  7688.  The output of this example is as follows:
  7689.  
  7690.  1:Contents of string1
  7691.  
  7692.  2:Contents of string2
  7693.  
  7694.  3:Contents of string2, again
  7695.  
  7696.  4:Contents of string1
  7697.  5:Contents of string2, but not string1
  7698.  
  7699.  6:Contents of string2, and also string1
  7700.  7:Contents of string2, and also string1
  7701.  
  7702.  
  7703.  160. _Settexwindow() and Scrolling
  7704.  
  7705.  Product Version(s): 5.00 5.10
  7706.  Operating System:   MS-DOS
  7707.  Flags: ENDUSER | docerr
  7708.  Last Modified: 21-DEC-1988    ArticleIdent: Q36947
  7709.  
  7710.  Problem:
  7711.  
  7712.  The _settextwindow() function specifies a window where the text output
  7713.  to the screen is displayed. When the text window is full, the
  7714.  uppermost line scrolls up and out of the window. This scrolling occurs
  7715.  in most cases, but not all. The _settextwindow function knows to
  7716.  scroll the text in the window if the current line being written to is
  7717.  the last line in the window and one of either the following situations
  7718.  occurs:
  7719.  
  7720.  1. The string being printed ends with a carriage control
  7721.     character, '\n'.
  7722.  
  7723.  2. The string wraps onto the next line. (In this case, the
  7724.     wrapping is enabled by a _wrapon(_GWRAPON) call.)
  7725.  
  7726.  The text in the window will not scroll if these conditions are not
  7727.  met. More than likely, the last line in the window will be
  7728.  over-written.
  7729.  
  7730.  This is expected behavior for the _settextwindow and related
  7731.  functions.
  7732.  
  7733.  The examples below assume that the text window is defined by the
  7734.  coordinates (1,1, 14,80).
  7735.  
  7736.  The following example causes the text window to scroll because the
  7737.  second _outtext call (which prints to the last line in the window)
  7738.  ends in a carriage return character, '\n':
  7739.  
  7740.          _settextposition (13,1) ;       /* set cursor to 2nd to    */
  7741.                                          /* last line in the window.*/
  7742.  
  7743.          _outtext ("This will appear on line 13\n") ;
  7744.          _outtext ("This will appear on the last line (14)\n") ;
  7745.          _outtext ("The text window has now scrolled.") ;
  7746.  
  7747.  The following example also scrolls because the text output on the
  7748.  final line in the window wraps around to the next line:
  7749.  
  7750.          _wrapon (_GWRAPON) ;            /* enable wrapping of text.*/
  7751.          _settextposition (14,1) ;       /* set cursor to last line.*/
  7752.          _outtext ("This will be forty characters in length..") ;
  7753.          _outtext ("This will wrap around the right window border") ;
  7754.  
  7755.  The example below will not scroll the text window. The second
  7756.  _outtext() will just over-write the first. It will not scroll because
  7757.  wrapping has been disabled, and there is no carriage control character
  7758.  to signal the window to scroll.
  7759.  
  7760.  The following example demonstrates this behavior:
  7761.  
  7762.          _wrapon (_GWRAPOFF) ;           /* disable wrapping of text*/
  7763.          _settextposition (14,1) ;       /* set cursor to last line.*/
  7764.          _outtext ("This will appear on the last line (line 14)...") ;
  7765.          _settextposition (14,1) ;       /* set cursor to last line.*/
  7766.          _outtext ("This will over-write, not scroll.") ;
  7767.  
  7768.  
  7769.  
  7770.  161. Warning C1015 May be Caused by Lack of Available File Handles
  7771.  
  7772.  Product Version(s): 5.10   | 5.10
  7773.  Operating System:   MS-DOS | OS/2
  7774.  Flags: ENDUSER |
  7775.  Last Modified: 11-JAN-1990    ArticleIdent: Q36953
  7776.  
  7777.  Compiler error C1015, which is not documented in the text, is often
  7778.  caused by an error finding or opening an include file. This new error
  7779.  message is noted in the C Version 5.10 file ERRMSG.DOC.
  7780.  
  7781.  This error can occur if the INCLUDE environment variable has
  7782.  not been set correctly for your include file directory or the TMP
  7783.  variable is set to a Ram Disk.
  7784.  
  7785.  Especially under DOS, this error also can be generated by not having
  7786.  enough file handles available. (A file handle is an integer used by
  7787.  the operating system to keep track of every open file.) The number of
  7788.  file handles available to DOS can be increased from the default of
  7789.  eight to a number up to 20 (or higher with some OEM adaptations of
  7790.  MS-DOS versions later than Version 3.20) by placing the following line
  7791.  in CONFIG.SYS and rebooting your computer:
  7792.  
  7793.  FILES=20
  7794.  
  7795.  It  has been reported that if you do not set files above the default
  7796.  of eight, error C1015 appears soon after compilation begins. Setting
  7797.  files to 20 corrects the problem.
  7798.  
  7799.  File handles will typically be used during compilation and linkage by
  7800.  the CL driver, the compiler passes, your C source code file, include
  7801.  files, the linker, libraries, and temporary files created by the
  7802.  compiler or linker.
  7803.  
  7804.  Closing a file makes its handle available to the operating system
  7805.  again, so the lack of available file handles refers to the number of
  7806.  files open at any one time.
  7807.  
  7808.  
  7809.  162. C2086, C2061 on CFLOW.C when Language Extentions Not Enabled
  7810.  
  7811.  Product Version(s): 5.00 5.10 | 5.10
  7812.  Operating System:   MS-DOS    | OS/2
  7813.  Flags: ENDUSER |
  7814.  Last Modified: 12-DEC-1988    ArticleIdent: Q36955
  7815.  
  7816.  Compiling the sample program CFLOW.C with language extensions disables
  7817.  results in the following errors:
  7818.  
  7819.  cflow.c(4) : error C2086: 'size_t' : redefinition
  7820.  cflow.c(934) : error C2061: syntax error : identifier 'c'
  7821.  
  7822.  The Microsoft extensions to C can be disabled by compiling with
  7823.  the option /Za (enforce ANSI compatibility) or, when in QuickC,
  7824.  clearing the X from the Language Extensions check box in the Compile
  7825.  dialog box.
  7826.  
  7827.  The C2086 error occurs because both CFLOW.C and STDIO.H have the following:
  7828.  
  7829.  typedef unsigned int size_t;
  7830.  
  7831.  Redefinition of a typedef is a language extension. This information is
  7832.  stated in the "Microsoft C Optimizing Compiler User's Guide" on Page
  7833.  100.
  7834.  
  7835.  The C2061 error occurs on the line
  7836.  
  7837.  static int near c;
  7838.  
  7839.  because the keyword "near" is an extension to C, and so is understood
  7840.  by the compiler to be the simple identifier being defined, leaving the
  7841.  now-surplus "c" to be flagged as syntactically incorrect. This
  7842.  information is documented in the user's guide on Page 99.
  7843.  
  7844.  
  7845.  163. Warning C4067 Unexpected Characters Following 'directive'
  7846.  
  7847.  Product Version(s): 5.00 5.10 | 5.10
  7848.  Operating System:   MS-DOS    | OS/2
  7849.  Flags: ENDUSER | S_QUICKC S_ERROR
  7850.  Last Modified: 12-DEC-1988    ArticleIdent: Q36992
  7851.  
  7852.  The warning below is from Section D.1.3 (Page 340) of the "Microsoft
  7853.  QuickC Programmer's Guide" and Section E.3.3 (Page 269) of the
  7854.  "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7855.  5.10.
  7856.  
  7857.  This message indicates potential problems but does not hinder
  7858.  compilation and linking. The number in parentheses at the end of a
  7859.  warning-message description gives the minimum warning level that must
  7860.  be set for the message to appear.
  7861.  
  7862.  The following is the warning:
  7863.  
  7864.  C4067       unexpected characters following 'directive' directive-
  7865.              newline expected
  7866.  
  7867.              Extra characters followed a preprocessor directive, as
  7868.              in the following example:
  7869.  
  7870.              #endif  NO_EXT_KEYS
  7871.  
  7872.              This is accepted in Version 3.0, but not in Versions
  7873.              4.0 and 5.0.  Versions 4.0 and 5.0 require comment
  7874.              delimeters, such as the following:
  7875.  
  7876.              #endif  /* NO_EXT_KEYS */
  7877.  
  7878.  As with Versions 4.00, 5.00, and 5.10 of the C optimizing compiler,
  7879.  QuickC Versions 1.00 and 1.01 do not accept the extra characters
  7880.  unless surrounded by comment delimeters.
  7881.  
  7882.  
  7883.  164. Warning C4077 Unknown check_stack Option
  7884.  
  7885.  Product Version(s): 5.00 5.10 | 5.10
  7886.  Operating System:   MS-DOS    | OS/2
  7887.  Flags: ENDUSER | S_QUICKC S_ERROR
  7888.  Last Modified: 12-DEC-1988    ArticleIdent: Q37001
  7889.  
  7890.  The warning below is from Section D.1.3 (Page 349) of the "Microsoft
  7891.  QuickC Programmer's Guide" and Section E.3.3 (Page 278) of the
  7892.  "Microsoft C Optimizing Compiler User's Guide" for Versions 5.00 and
  7893.  5.10.
  7894.  
  7895.  This message indicates potential problems but does not hinder
  7896.  compilation and linking. The number in parentheses at the end of a
  7897.  warning-message description gives the minimum warning level that must
  7898.  be set for the message to appear.
  7899.  
  7900.  C4077       unkown check_stack option
  7901.  
  7902.              An unknown option was given with the old form of the
  7903.              'check_stack' pragma, as in the following example:
  7904.  
  7905.              #pragma check_stack yes
  7906.  
  7907.              In the old form of the check_stack pragma, the argument
  7908.              to the argument to the pragma must be empty, +, or -. (1)
  7909.  
  7910.  The following is an example of using the check_stack pragma:
  7911.  
  7912.        syntax           Compiled with /Gs       Action
  7913.                          (Pointer Check)
  7914.  
  7915.  #pragma check_stack()        yes            Turns off Stack checking
  7916.                                              for routines that follow.
  7917.  #pragma check_stack()        no             Turns on Stack checking
  7918.                                              for routines that follow.
  7919.  #pragma check_stack(on)      yes or no      Turns on Stack checking
  7920.                                              for routines that follow.
  7921.  #pragma check_stack(off)     yes or no      Turns off Stack checking
  7922.                                              for routines that follow.
  7923.  
  7924.  Note: for earlier versions of Microsoft C, the check_stack pragma had
  7925.  a different format. check_stack+ was to enable stack checking and
  7926.  check_stack- was to disable stack checking. Although the Microsoft
  7927.  Optimizing compiler still accepts this format, its use is discouraged
  7928.  because it may not be supported in future versions.
  7929.  
  7930.  This information was taken from Page 98 of the C user's guide and
  7931.  Page 169 of the QuickC programmer's guide.
  7932.  
  7933.  
  7934.  165. Warning C4086 Expected
  7935.  
  7936.  Product Version(s): 5.00 5.10 | 5.10
  7937.  Operating System:   MS-DOS    | OS/2
  7938.  Flags: ENDUSER | S_QUICKC S_ERROR
  7939.  Last Modified: 12-DEC-1988    ArticleIdent: Q37004
  7940.  
  7941.  The warning below is from Section D.1.3 (Page 340) of the "Microsoft
  7942.  QuickC Programmer's Guide" and Section E.3.3 (Page 269) of the
  7943.  "Microsoft C Optimizing Compiler User's Guide" for Version 5.00 and
  7944.  5.10.
  7945.  
  7946.  This message indicates potential problems but does not hinder
  7947.  compilation and linking. The number in parentheses at the end of a
  7948.  warning-message description gives the minimum warning level that must
  7949.  be set for the message to appear.
  7950.  
  7951.  The following is the warning:
  7952.  
  7953.  C4086       expected [1|2|4]
  7954.  
  7955.              An invalid argument was given for a "pack" pragma, as
  7956.              in the following example:
  7957.  
  7958.              #pragma pack (yes)
  7959.  
  7960.  The "pack" pragma is used when you want to specify packing other than
  7961.  the packing specified on the command line for particular structures.
  7962.  The /Zp option and the "pack" pragma control how structure data are
  7963.  packed into memory.
  7964.  
  7965.  For detailed information on the /Zp option and the "pack" pragma, see
  7966.  Page 210 of the QuickC programmer's guide and Page 100 of the C user's
  7967.  guide.
  7968.  
  7969.  
  7970.  166. How to Determine the Amount of Available DOS Memory
  7971.  
  7972.  Product Version(s): 5.00 5.10
  7973.  Operating System:   MS-DOS
  7974.  Flags: ENDUSER |
  7975.  Last Modified: 12-DEC-1988    ArticleIdent: Q37022
  7976.  
  7977.  Question:
  7978.  
  7979.  Is there a C run-time function that I can use to determine how much
  7980.  RAM is available under DOS?
  7981.  
  7982.  Response:
  7983.  
  7984.  No function exists that specifically performs this task. Functions
  7985.  "_freect" or "_memavl" only return available memory for dynamic
  7986.  allocation in the near heap. The near heap is located above the stack
  7987.  within the 64K byte or smaller default data segment called DGROUP.
  7988.  Function _memavl indicates the amount of near space that never has
  7989.  been allocated, whereas _freect allows you to detect what has been
  7990.  freed.
  7991.  
  7992.  However, you may use the function "_dos_allocmem" defined below
  7993.  to determine the amount of far heap above the default data segment:
  7994.  
  7995.      #include <dos.h>
  7996.      unsigned _dos_allocmem(size, segment) ;
  7997.      unsigned size ;
  7998.      unsigned *segment ;
  7999.  
  8000.  If the attempted memory allocation is NOT successful, _dos_allocmem
  8001.  puts the maximum possible free memory size (in 16-byte paragraphs)
  8002.  in the word pointed to by "segment". If you request to allocate
  8003.  0xFFFF paragraphs of memory (which will fail in any case), you should
  8004.  be able to find out the amount of available memory. (DOS function
  8005.  call 48h performs the same task.)
  8006.  
  8007.  Note: the value returned to *segment is in paragraphs too. If other
  8008.  memory allocation functions are going to use this value, it should be
  8009.  converted to bytes.
  8010.  
  8011.  Refer to the "Microsoft C Version 5.10 Optimizing Compiler Run-time
  8012.  Library Reference" for specific information on using _dos_allocmem.
  8013.  
  8014.  
  8015.  167. Link Error No Stack Segment after Using Windows SDK Install
  8016.  
  8017.  Product Version(s): 5.00 5.10
  8018.  Operating System:   MS-DOS
  8019.  Flags: ENDUSER |
  8020.  Last Modified: 12-DEC-1988    ArticleIdent: Q37023
  8021.  
  8022.  If a C program generates linker errors stating that no stack segment
  8023.  exists and that there are several unresolved externals references made
  8024.  by the startup code, the program may have been linked with libraries
  8025.  modified by the Windows SDK Install program.
  8026.  
  8027.  The Windows install program modifies C libraries, upon your request,
  8028.  so that when linking Window applications it can look for the standard
  8029.  library names with no other linker options specified. A more detailed
  8030.  explanation can be found in the README.WRI on the Development
  8031.  Utilities Disk 1 that comes with Windows SDK Version 2.00.
  8032.  
  8033.  The install program retains the original C library. The library will
  8034.  have its same name with a "C" appended. For instance, SLIBCE.LIB will
  8035.  be copied to SLIBCEC.LIB. When you link with this library, make sure
  8036.  to use the /NOD option and specify the library by name.
  8037.  
  8038.  
  8039.  168. Setup Won't Accept Drive on Novell Network
  8040.  
  8041.  Product Version(s): 5.10   | 5.10
  8042.  Operating System:   MS-DOS | OS/2
  8043.  Flags: ENDUSER |
  8044.  Last Modified: 18-NOV-1988    ArticleIdent: Q37198
  8045.  
  8046.  Setup on Novell network Versions 2.0x gives "cannot create subdirectory
  8047.  G:\(etc.)" when trying to specify a destination for bound executables
  8048.  (i.e., the first question about paths that the setup program asks).
  8049.  
  8050.  It will not install on a network because it is illegal to do so
  8051.  without a special licensing agreement with Microsoft. If you have this
  8052.  agreement you receive a setup program that installs on the network.
  8053.  
  8054.  This scenario should not be confused with the situation of someone
  8055.  installing Microsoft software on their immediate machine and using
  8056.  network drives to store files they have created. This process is
  8057.  allowed.
  8058.  
  8059.  
  8060.  169. Coordinates Incorrect in Run-Time Library Manual
  8061.  
  8062.  Product Version(s): 5.00 5.10
  8063.  Operating System:   MS-DOS
  8064.  Flags: ENDUSER | docerr
  8065.  Last Modified: 18-NOV-1988    ArticleIdent: Q37199
  8066.  
  8067.  Page 51 of the "Microsoft C Run-Time Library Manual" states that the
  8068.  range of physical coordinates is (0,0) to (640, 350). This information
  8069.  is incorrect. The correct range of physical coordinates is (0,0) to
  8070.  (639, 349).
  8071.  
  8072.  
  8073.  170. Redirection with spawn() or exec()
  8074.  
  8075.  Product Version(s): 5.10
  8076.  Operating System:   MS-DOS
  8077.  Flags: ENDUSER | SR# S880925-1 s_quickc
  8078.  Last Modified: 18-NOV-1988    ArticleIdent: Q37200
  8079.  
  8080.  Question:
  8081.  
  8082.  There is a problem when you use spawnvp or spawnlp to invoke the
  8083.  SORT.EXE that usually comes with DOS. When you run the program, it
  8084.  seems that SORT.EXE starts, but then it does nothing. The behavior is
  8085.  similar to starting SORT.EXE from the DOS prompt without any arguments.
  8086.  
  8087.  How do I do any redirection with spawn() or exec()?
  8088.  
  8089.  Response::
  8090.  
  8091.  Use the system() function. For example, you can make a run SORT.EXE
  8092.  by executing the following:
  8093.  
  8094.     system("SORT <INFILE >OUTFILE");
  8095.  
  8096.  This process has the minor disadvantage of taking up extra memory for
  8097.  another copy of COMMAND.COM. This behavior shouldn't be a problem
  8098.  unless you're short on available memory. If you do not have very much
  8099.  memory, the following information may help.
  8100.  
  8101.  Because COMMAND.COM, and NOT the EXEC loader, handles redirection,
  8102.  this behavior is expected. Child processes inherit the handles of
  8103.  their parents; therefore, to redirect the input and output of the
  8104.  child, change the definitions of STDIN and STDOUT in the
  8105.  parent process. The proper way to redirect input for a filter is
  8106.  described starting on Page 441 of the "MS-DOS Encyclopedia," along with
  8107.  a complete MASM example.
  8108.  
  8109.  Note: the dup and dup2 functions in the C Version 5.10 run-time
  8110.  library are the same as the INT 21h functions 45h and 46h,
  8111.  respectively.
  8112.  
  8113.  There also are partial examples of this technique on Page 230 of the
  8114.  "Microsoft C 5.1 Run-Time Library Reference" manual and on page 353 of
  8115.  "Advanced MS-DOS Programming" (by Duncan, published by Microsoft
  8116.  Press).
  8117.  
  8118.  It is possible to use freopen() to redefine STDIN and STDOUT; however,
  8119.  doing so causes any redirection that may have been performed on the
  8120.  parent process to be lost.
  8121.  
  8122.  
  8123.  171. System Memory Allocation Error after Using halloc or malloc
  8124.  
  8125.  Product Version(s): 5.00 5.10
  8126.  Operating System:   MS-DOS
  8127.  Flags: ENDUSER | SR# S880914-27
  8128.  Last Modified: 18-NOV-1988    ArticleIdent: Q37201
  8129.  
  8130.  After running a program you have created that uses malloc or
  8131.  halloc functions, DOS may print the following message:
  8132.  
  8133.  Memory Allocation Error
  8134.  Cannot Load COMMAND.COM.
  8135.  
  8136.  You are able to allocate, use, write, read, and free memory, but when
  8137.  your program finishes, you receive the error. If you remove halloc()
  8138.  from your program, it terminates normally.
  8139.  
  8140.  Your program is probably writing outside of a memory block you
  8141.  allocated using halloc or malloc. DOS maintains information about
  8142.  memory usage in blocks immediately preceding the area you're given.
  8143.  This error is usually are result of overwriting these information
  8144.  blocks. The solution is to find out where you're overwriting DOS's
  8145.  memory and avoid doing it.
  8146.  
  8147.  Note: this error can also be the result of writing PAST the end of a
  8148.  block because you could corrupt the list entry for the NEXT block.
  8149.  
  8150.  You can determine where the overwrite occurs by using CodeView to set
  8151.  a tracepoint on the space after the allocated block. If you don't have
  8152.  enough memory to run CodeView, you can narrow down the problem by
  8153.  using a pointer to check those bytes at selected points in your
  8154.  program.
  8155.  
  8156.  
  8157.  172. Operator sizeof Returns Type size_t, Defined as unsigned int
  8158.  
  8159.  Product Version(s): 5.00 5.10 | 5.10
  8160.  Operating System:   MS-DOS    | OS/2
  8161.  Flags: ENDUSER | docerr
  8162.  Last Modified: 21-NOV-1988    ArticleIdent: Q37205
  8163.  
  8164.  The sizeof operator returns a value that is of type size_t. The
  8165.  definition of size_t is implementation-dependent, according to the
  8166.  ANSI standard. In Microsoft C, the size_t type is defined in STDEF.H
  8167.  and in MALLOC.H as an unsigned int. This information is documented in
  8168.  the "Microsoft C Optimizing Compiler Run-Time Library Reference" on
  8169.  Pages 38 and 98.
  8170.  
  8171.  To use sizeof on huge items, which can be larger than 64K, you will
  8172.  need to use a typecast on the sizeof expression as follows:
  8173.  
  8174.     char huge a[95000];
  8175.     unsigned long sizea;
  8176.  
  8177.     sizea = (unsigned long) sizeof(a);
  8178.  
  8179.  Note: the Index entry for "size_t type" lists Pages 38 and 97; it
  8180.  should say Pages 38 and 98.
  8181.  
  8182.  The "Microsoft C Optimizing Compiler Language Reference" manual
  8183.  describes the sizeof operator on Pages 120-121, section 5.3.4, but
  8184.  does not give the return type.
  8185.  
  8186.  
  8187.  173. No Such Thing as a static auto Variable.
  8188.  
  8189.  Product Version(s): 5.00 5.10 | 5.00 5.10
  8190.  Operating System:   MS-DOS    | OS/2
  8191.  Flags: ENDUSER   | S_QUICKC docerr
  8192.  Last Modified: 21-NOV-1988    ArticleIdent: Q37219
  8193.  
  8194.  Page 86 (section 4.6.2, third paragraph) of the "Microsoft QuickC and
  8195.  Optimizing C Language Reference" states "A static auto variable can
  8196.  be initialized..."
  8197.  
  8198.  However, the storage classes static and auto are mutually exclusive --
  8199.  there is no "static auto" class. The text should read, "A static OR
  8200.  auto variable can be initialized..."
  8201.  
  8202.  
  8203.  174. Domain Error
  8204.  
  8205.  Product Version(s): 5.10   | 5.10
  8206.  Operating System:   MS-DOS | OS/2
  8207.  Flags: ENDUSER | s_quickc h_fortran s_pascal
  8208.  Last Modified: 21-NOV-1988    ArticleIdent: Q37223
  8209.  
  8210.  A domain error occurs when you pass an invalid value to a function.
  8211.  "Domain" refers to arguments to a function; "range" refers to the
  8212.  return values.
  8213.  
  8214.  For example, if you pass a -1 to sqrt(), you receive the math error
  8215.  "M6201 Domain Error" because -1 is not in the domain of the square
  8216.  root function (i.e., you can't take the square root of -1).
  8217.  
  8218.  This error also can occur if an incorrect type is passed to the
  8219.  function. (For example, passing an int to a function that expects
  8220.  double.) You should receive warnings in these cases if you have
  8221.  declared proper function prototypes (perhaps by including the math.h
  8222.  file).
  8223.  
  8224.  Make sure the value you pass to a function is of the proper type and
  8225.  the value is within that function's domain.
  8226.  
  8227.  
  8228.  175. Why "CDECL" Is Everywhere in Your Include Files
  8229.  
  8230.  Product Version(s): 5.00 5.10 | 5.10
  8231.  Operating System:   MS-DOS    | OS/2
  8232.  Flags: ENDUSER | s_quickc
  8233.  Last Modified: 26-OCT-1988    ArticleIdent: Q37233
  8234.  
  8235.  Question:
  8236.  
  8237.  When I look at the include files provided with the Microsoft C
  8238.  compiler, I see all the function prototypes prefixed with "_CDECL".
  8239.  Why?
  8240.  
  8241.  Response:
  8242.  
  8243.  When Microsoft extensions are enabled, the manifest constant "_CDECL"
  8244.  takes the value "cdecl", which says that the associated function takes
  8245.  standard C calling conventions. (C calling conventions are used by
  8246.  default except when the /Gc switch is specified during compilation.
  8247.  The /Gc switch tells the compiler to default to FORTRAN/Pascal-style
  8248.  function calling and naming conventions.)
  8249.  
  8250.  Thus, the _CDECL's on the function prototypes tell the compiler to
  8251.  generate the runtime library function calls using C calling and naming
  8252.  conventions always--even if the /Gc option is used.
  8253.  
  8254.  For more information, see the "Mixed Language Programming Guide" and
  8255.  the "Microsoft C Language Reference."
  8256.  
  8257.  
  8258.  176. Loadtime DLL Initialization for C 5.10
  8259.  
  8260.  Product Version(s): 5.10   | 5.10
  8261.  Operating System:   MS-DOS | OS/2
  8262.  Flags: ENDUSER | softlib CRTDLL.ARC S12104.EXE
  8263.  Last Modified: 21-SEP-1989    ArticleIdent: Q37355
  8264.  
  8265.  Question:
  8266.  
  8267.  How do I implement load-time DLL initialization without losing C
  8268.  run-time support for my DLL?
  8269.  
  8270.  Response:
  8271.  
  8272.  Single-Threaded DLLs (that use LLIBCDLL.LIB)
  8273.  
  8274.  There is an object module DLLINIT.OBJ that must be linked with your
  8275.  routine. You must make an explicit call to C_INIT() to bring in
  8276.  the C run-time startup code. If you are going to use DosLoadModule()
  8277.  and DosFreeModule() to bring in and remove your DLL, then you must also
  8278.  link in DLLTERM.OBJ. No explicit calls are necessary to use this
  8279.  routine.
  8280.  
  8281.  Multi-Threaded DLLs
  8282.  
  8283.  There is an object module CRTDLL_I.OBJ that replaces the CRTDLL.OBJ
  8284.  that comes with the C package. You should use CRTDLL_I.OBJ in the
  8285.  exact same manner you would use CRTDLL.OBJ. You must also make a
  8286.  reference to C_INIT() in your initialization routine. The prototype is
  8287.  as follows:
  8288.  
  8289.     void far
  8290.     pascal C_INIT();.
  8291.  
  8292.  All three object modules are in the Software Library archive file
  8293.  CRTDLL.ARC. This file can be found in the Software Library by
  8294.  searching on the filename CRTDLL.ARC, the Q number of this article, or
  8295.  S12104.
  8296.  
  8297.  
  8298.  177. "pascal" Attribute for Multi-Thread Functions Returning Double
  8299.  
  8300.  Product Version(s): 5.10
  8301.  Operating System:   OS/2
  8302.  Flags: ENDUSER |
  8303.  Last Modified: 22-NOV-1988    ArticleIdent: Q37459
  8304.  
  8305.  Although it is not documented, an important requirement for returning
  8306.  floating-point values from functions in a multi-thread environment is
  8307.  defining and prototyping functions with the "pascal" function
  8308.  attribute as we have done for all functions prototyped to return a
  8309.  double in \include\mt\math.h.
  8310.  
  8311.  When you use the pascal attribute on floating-point functions, the
  8312.  floating-point return value is placed on the calling thread's stack,
  8313.  providing each thread with its own return value as desired.
  8314.  
  8315.  When using the default of the C function call/return convention
  8316.  instead of pascal, we use a global variable __fac (floating-point
  8317.  accumulator) for returning floating-point values. For multi-thread
  8318.  applications or DLL's using CRTLIB.DLL, the global variable __fac
  8319.  could be unintentionally modified by another thread, so it is not
  8320.  contained in CRTEXE.OBJ, CRTDLL.OBJ, or CRTDLL.LIB. Consequently,
  8321.  references to __fac will be unresolved at link time.
  8322.  
  8323.  
  8324.  178. Scan Codes for IBM and Compatible Keyboards
  8325.  
  8326.  Product Version(s): 4.00 5.00 5.10 | 5.10
  8327.  Operating System:   MS-DOS         | OS/2
  8328.  Flags: ENDUSER |
  8329.  Last Modified:  8-NOV-1988    ArticleIdent: Q37617
  8330.  
  8331.  Below are the scan codes for IBM and compatible keyboards. All scan
  8332.  codes are in hexadecimal. See the "IBM PC Technical Reference" for more
  8333.  details.
  8334.  
  8335.  The scan codes are as follows:
  8336.  
  8337.  83 key (PC,PC/XT)       84 key (PC/AT)        101/102 key (PC/AT PS/2)
  8338.  
  8339.  Key     Scan Code       Key     Scan Code       Key     Scan Code
  8340.  
  8341.  ESC         01          KP ESC      01          ESC         01
  8342.  1           02          1           02          1           02
  8343.  2           03          2           03          2           03
  8344.  3           04          3           04          3           04
  8345.  4           05          4           05          4           05
  8346.  5           06          5           06          5           06
  8347.  6           07          6           07          6           07
  8348.  7           08          7           08          7           08
  8349.  8           09          8           09          8           09
  8350.  9           0A          9           0A          9           0A
  8351.  0           0B          0           0B          0           0B
  8352.  -           0C          -           0C          -           0C
  8353.  =           0D          =           0D          =           0D
  8354.  BACKSPACE   0E          BACKSPACE   0E          BACKSPACE   0E
  8355.  TAB         0F          TAB         0F          TAB         0F
  8356.  Q           10          Q           10          Q           10
  8357.  W           11          W           11          W           11
  8358.  E           12          E           12          E           12
  8359.  R           13          R           13          R           13
  8360.  T           14          T           14          T           14
  8361.  Y           15          Y           15          Y           15
  8362.  U           16          U           16          U           16
  8363.  I           17          I           17          I           17
  8364.  O           18          O           18          O           18
  8365.  P           19          P           19          P           19
  8366.  [           1A          [           1A          [           1A
  8367.  ]           1B          ]           1B          ]           1B
  8368.  RETURN      1C          RETURN      1C          RETURN      1C
  8369.  CTRL        1D          CTRL        1D          L CTRL      1D
  8370.  A           1E          A           1E          A           1E
  8371.  S           1F          S           1F          S           1F
  8372.  D           20          D           20          D           20
  8373.  F           21          F           21          F           21
  8374.  G           22          G           22          G           22
  8375.  H           23          H           23          H           23
  8376.  J           24          J           24          J           24
  8377.  K           25          K           25          K           25
  8378.  L           26          L           26          L           26
  8379.  ;           27          ;           27          ;           27
  8380.  '           28          '           28          '           28
  8381.  `           29          ESC         29          `           29
  8382.  L SHIFT     2A          L SHIFT     2A          L SHIFT     2A
  8383.  Z           2C          Z           2C          Z           2C
  8384.  X           2D          X           2D          X           2D
  8385.  C           2E          C           2E          C           2E
  8386.  V           2F          V           2F          V           2F
  8387.  B           30          B           30          B           30
  8388.  N           31          N           31          N           31
  8389.  M           32          M           32          M           32
  8390.  ,           33          ,           33          ,           33
  8391.  .           34          .           34          .           34
  8392.  /           35          /           35          /           35
  8393.  R SHIFT     36          R SHIFT     36          R SHIFT     36
  8394.  PRT SCR     37          PRT SCR     37          KP *        37
  8395.  ALT         38          ALT         38          ALT         38
  8396.  Space       39          Space       39          Space       39
  8397.  CAPS LOCK   3A          CAPS LOCK   3A          CAPS LOCK   3A
  8398.  F1          3B          F1          3B          F1          3B
  8399.  F2          3C          F2          3C          F2          3C
  8400.  F3          3D          F3          3D          F3          3D
  8401.  F4          3E          F4          3E          F4          3E
  8402.  F5          3F          F5          3F          F5          3F
  8403.  F6          40          F6          40          F6          40
  8404.  F7          41          F7          41          F7          41
  8405.  F8          42          F8          42          F8          42
  8406.  F9          43          F9          43          F9          43
  8407.  F10         44          F10         44          F10         44
  8408.  NUM LOCK    45          NUM LOCK    45          NUM LOCK    45
  8409.  SCROLL LOCK 46          SCROLL LOCK 46          SCROLL LOCK 46
  8410.  KP 7        47          KP 7        47          KP 7        47
  8411.  KP 8        48          KP 8        48          KP 8        48
  8412.  KP 9        49          KP 9        49          KP 9        49
  8413.  KP -        4A          KP -        4A          KP -        4A
  8414.  KP 4        4B          KP 4        4B          KP 4        4B
  8415.  KP 5        4C          KP 5        4C          KP 5        4C
  8416.  KP 6        4D          KP 6        4D          KP 6        4D
  8417.  KP +        4E          KP +        4E          KP +        4E
  8418.  KP 1        4F          KP 1        4F          KP 1        4F
  8419.  KP 2        50          KP 2        50          KP 2        50
  8420.  KP 3        51          KP 3        51          KP 3        51
  8421.  KP 0        52          KP 0        52          KP 0        52
  8422.  KP .        53          KP .        53          KP .        53
  8423.                          Sys Req     54          F11         57
  8424.                                                  F12         58
  8425.                                                  R CTRL      E0 10
  8426.                                                  KP /        E0 36
  8427.                                                  R ALT       E0 38
  8428.                                                  RIGHT ARROW E0 40
  8429.                                                  HOME        E0 47
  8430.                                                  UP ARROW    E0 48
  8431.                                                  PAGE UP     E0 49
  8432.                                                  LEFT ARROW  E0 4B
  8433.                                                  END         E0 4F
  8434.                                                  DOWN ARROW  E0 50
  8435.                                                  PAGE DOWN   E0 51
  8436.                                                  INSERT      E0 52
  8437.                                                  DELETE      E0 53
  8438.                                                  KP ENTER    E0 1C
  8439.                                                  PAUSE       E1 10 45
  8440.                                                  PRINT SCR   E0 2A E037
  8441.  
  8442.  (Source : Norton's Guide to the IBM PC and PS/2)
  8443.  
  8444.  
  8445.  179. Backslash Character Interpreted In /Ss and /St Options
  8446.  
  8447.  Product Version(s): 5.00 5.10 | 5.10
  8448.  Operating System:   MS-DOS    | OS/2
  8449.  Flags: ENDUSER |
  8450.  Last Modified: 14-NOV-1988    ArticleIdent: Q37619
  8451.  
  8452.  When specifying the /St and /Ss for titles and subtitles in your
  8453.  source listing, you must use double-backslash (\\) marks if you want
  8454.  your title or subtitle to contain a single backslash. If you do not
  8455.  include the second backslash, the next character will be interpreted
  8456.  as an escape character.
  8457.  
  8458.  
  8459.  180. EOH Is Not a Defined Constant for getch or getche
  8460.  
  8461.  Product Version(s): 5.00 5.10 | 5.10
  8462.  Operating System:   MS-DOS    | OS/2
  8463.  Flags: ENDUSER |
  8464.  Last Modified: 14-NOV-1988    ArticleIdent: Q37620
  8465.  
  8466.  The "Microsoft C 5.10 Optimizing Compiler Run-Time Library Reference"
  8467.  manual for the functions getch and getche states that when reading a
  8468.  function or cursor key, the first call to either function will return
  8469.  0 or EOH. This is misleading; EOH appears to be a constant that is
  8470.  defined in an include file, though it is not. These functions actually
  8471.  return 0 or 0xE0. The 0x convention is followed throughout the manual
  8472.  for hexadecimal numbers, except in this case.
  8473.  
  8474.  
  8475.  181. Amount of Disk Space Needed for Minimum C 5.10 Setup for DOS
  8476.  
  8477.  Product Version(s): 5.10
  8478.  Operating System:   MS-DOS
  8479.  Flags: ENDUSER |
  8480.  Last Modified: 14-NOV-1988    ArticleIdent: Q37621
  8481.  
  8482.  Question:
  8483.  
  8484.  How much disk space will I need to set up the Microsoft C Version 5.10
  8485.  Compiler in a minimum configuration for DOS?
  8486.  
  8487.  Response:
  8488.  
  8489.  In a minimum configuration, you will need to have about 1.45 megabytes
  8490.  of disk space available. This includes the small, medium, and graphics
  8491.  libraries and all include files and passes of the compiler.
  8492.  
  8493.  This does not include any user source code, temporary files, the
  8494.  Microsoft editor, CodeView or any utilities.
  8495.  
  8496.  Although you will be able to use the compiler in this minimum setup,
  8497.  we recommend that you have about 2.5 megabytes of disk space and do a
  8498.  complete setup.
  8499.  
  8500.  
  8501.  182. Using Function Name Without "()" Produces No Code
  8502.  
  8503.  Product Version(s): 5.10   | 5.10
  8504.  Operating System:   MS-DOS | OS/2
  8505.  Flags: ENDUSER | S_QuickC
  8506.  Last Modified: 17-JUL-1990    ArticleIdent: Q50234
  8507.  
  8508.  When a function name declared in your program is used without
  8509.  parentheses, the compiler does not produce any code. The compiler does
  8510.  not produce error messages or warnings as long as the function has
  8511.  been prototyped. This occurs regardless of whether or not the function
  8512.  takes parameters because the compiler calculates the function address,
  8513.  but because the function call operator "()" is not present, no call is
  8514.  made. This result is similar to the following:
  8515.  
  8516.     int a;
  8517.  
  8518.     a;      /* no code generated here either */
  8519.  
  8520.  Code Example
  8521.  ------------
  8522.  
  8523.  void foo(int a, int b);
  8524.  void main(void)
  8525.  {
  8526.       foo;               /* Using foo without function call operator () */
  8527.  }
  8528.  
  8529.  The above code compiles and links correctly without errors or warnings
  8530.  but produces no code in reference to foo(). For this to work
  8531.  correctly, add the function call operator "()".
  8532.  
  8533.  
  8534.  183. Using a Logical AND Operation && and OR Operation ||
  8535.  
  8536.  Product Version(s): 5.10   | 5.10
  8537.  Operating System:   MS-DOS | OS/2
  8538.  Flags: ENDUSER | S_QuickC
  8539.  Last Modified: 16-NOV-1988    ArticleIdent: Q37624
  8540.  
  8541.  Question:
  8542.  
  8543.  Why does the statement for the integers a, b, c, and d result in
  8544.  values of 1 for a, 2 for b, but 0 for c and d in the following
  8545.  example?
  8546.  
  8547.     a = (b = 2) || (c = 3) && (d = 4)
  8548.  
  8549.  I thought that the logical AND operation && would be performed before
  8550.  the logical OR operation ||, so that c and d would be assigned 3 and
  8551.  4. The "Microsoft C 5.1 Optimizing Compiler Reference," Page 137
  8552.  states "Expressions with higher-precedence operators are evaluated
  8553.  first."
  8554.  
  8555.  Response:
  8556.  
  8557.  While it's true that logical AND has a higher precedence than logical
  8558.  OR, precedence in C means how operands are grouped, not necessarily
  8559.  the order in which they are evaluated. The documentation is incorrect
  8560.  on this point.
  8561.  
  8562.  The following
  8563.  
  8564.     lvalue = operand1 || operand2 && operand3;
  8565.  
  8566.  will be grouped as follows:
  8567.  
  8568.     lvalue = operand1 || (operand2 && operand3);
  8569.  
  8570.  However, this does not mean (operand2 && operand3) will be evaluated
  8571.  first in the above statement. In fact, this statement is a logical OR
  8572.  expression with two operands: operand1 and (operand2 && aoperand3).
  8573.  Operands are defined as an entity on which an operator acts; in this
  8574.  case the logical OR operator || acts on operand1 and (operand2 &&
  8575.  operand3). Logical OR expressions are evaluated in left-to-right
  8576.  order, so operand1 will be evaluated first.
  8577.  
  8578.  As noted in the proposed ANSI C standard, section 3.3.14 of both the
  8579.  November 1987 and May 1988 drafts for the logical OR operator, "If the
  8580.  first operand compares unequal to 0, the second operand is not
  8581.  evaluated." In this case, if operand1 != 0, (operand2 && operand3)
  8582.  will not be evaluated. This is the behavior of both the C Version 5.10
  8583.  and QuickC Version 1.01 compilers. This behavior has been a feature
  8584.  of C since the original K & R, and is so handy that many modern
  8585.  Pascal compilers now provide this functionality.
  8586.  
  8587.  The following example demonstrates this behavior:
  8588.  
  8589.  #include <stdio.h>
  8590.  int a,b,c,d;
  8591.  main() {
  8592.      a = (b = 2) || (c = 3) && (d = 4);
  8593.      printf("a = %d, b = %d, c = %d, d = %d\n",a,b,c,d);
  8594.      }
  8595.  
  8596.  The following is an example of output resulting from a program
  8597.  
  8598.     a = 1, b = 2, c = 0, d = 0
  8599.  
  8600.  Because (b = 2) is not 0, no further evaluations are performed, and c
  8601.  and d are not assigned 3 and 4. If the intent is to assign values to
  8602.  variables, then separate assignment statements should be made.
  8603.  
  8604.  As noted in "The C Programming Language", second edition by Kernighan
  8605.  and Ritchie, Page 54, "The moral is that writing code that depends on
  8606.  the order of evaluation is a bad programming practice in any
  8607.  language."
  8608.  
  8609.  
  8610.  184. MKTEMP() Function Example Clarification
  8611.  
  8612.  Product Version(s): 5.10   | 5.10
  8613.  Operating System:   MS-DOS | OS/2
  8614.  Flags: ENDUSER | s_quickc
  8615.  Last Modified: 14-NOV-1988    ArticleIdent: Q37625
  8616.  
  8617.  The mktemp() function example in the "Microsoft C Optimizing Compiler
  8618.  Run-Time Library Reference" manual is correct. However, it is not
  8619.  clear that the following code statements are required:
  8620.  
  8621.     strcpy (names[i], template) ;
  8622.     result = mktemp(names[i]) ;
  8623.  
  8624.  These statements ensure that mktemp() is given the original template
  8625.  for each successive call. In the example, the template is defined
  8626.  as "fnXXXXXX". The first call to mktemp() will produce a file
  8627.  name of "fn000001". If you submit such a filename instead of
  8628.  the template, "fnXXXXXX", mktemp() will fail because it is unable
  8629.  to generate another unique name.
  8630.  
  8631.  The following example demonstrates this behavior:
  8632.  
  8633.  /*****************************************************************/
  8634.  /* This is the mktemp example in the "Microsoft QuickC Run-Time  */
  8635.  /* Library Reference" manual on Page 433. The example copies the */
  8636.  /* template to temporary storage so as not to destroy the        */
  8637.  /* original template.                                            */
  8638.  /*****************************************************************/
  8639.  
  8640.  #include <io.h>
  8641.  #include <stdio.h>
  8642.  
  8643.  char *template = "fnXXXXXX";
  8644.  char *result;
  8645.  char names[5][9];
  8646.  
  8647.  main()
  8648.  {
  8649.      int i;
  8650.  
  8651.      for (i=0;i<5;i++) {
  8652.          strcpy(names[i], template);      /* Save the template...   */
  8653.          result = mktemp(template);       /* Get another file name. */
  8654.          if (result == NULL)
  8655.              printf("Problem creating the tempfile");
  8656.          else{
  8657.              printf("the unique file name is %s\n",result);
  8658.              fopen(result, "w");
  8659.              }
  8660.                         }
  8661.  )
  8662.  
  8663.  Without the two commented lines in this example, this code fragment
  8664.  generates one unique name, then terminates as the pointer "result"
  8665.  becomes NULL because mktemp() cannot generate another unique name with
  8666.  the template given.
  8667.  
  8668.  
  8669.  185. _malloc Should Be malloc in Reference Manual
  8670.  
  8671.  Product Version(s): 5.00 5.10 | 5.10
  8672.  Operating System:   MS-DOS    | OS/2
  8673.  Flags: ENDUSER | docerr
  8674.  Last Modified:  8-NOV-1988    ArticleIdent: Q37626
  8675.  
  8676.  The "Microsoft C Optimizing Compiler Run-Time Library Reference"
  8677.  manual has a documentation error on Page 410, in the "malloc,
  8678.  _fmalloc, _nmalloc" entry. The third paragraph in the Return Value
  8679.  section states the following:
  8680.  
  8681.     The _malloc and _nmalloc functions...
  8682.  
  8683.  It should state the following:
  8684.  
  8685.     The malloc and _nmalloc functions...
  8686.  
  8687.  
  8688.  186. How errno Is Handled in Multi-Threaded Programs
  8689.  
  8690.  Product Version(s): 5.10
  8691.  Operating System:   OS/2
  8692.  Flags: ENDUSER | docerr
  8693.  Last Modified: 16-NOV-1988    ArticleIdent: Q37633
  8694.  
  8695.  The "Microsoft C for MS OS/2 and MS-DOS Operating Systems: Version 5.1
  8696.  Update" manual does not explain how errno is handled in multi-threaded
  8697.  programs. The following explains this information.
  8698.  
  8699.  In single-threaded programs, errno is a function returning an int, as
  8700.  can be observed by looking at the header file errno.h in the default
  8701.  include subdirectory. In the multi-thread case, errno is a function
  8702.  returning a pointer representing an array (as usual). This array has
  8703.  32 entries, one for each thread. OS/2 API routine calls are used to
  8704.  manage the assignation of threads to entries in this array. For the
  8705.  multi-thread libraries, errno is defined as follows:
  8706.  
  8707.   #define errno  *(__errno())
  8708.  
  8709.       where __errno is
  8710.  
  8711.   int far * far __errno( void );
  8712.  
  8713.       so "errno = EDOMAIN;" becomes "*(__errno()) = EDOMAIN;".
  8714.  
  8715.  You can determine the behavior at compile time because errno will be
  8716.  defined in the multi-thread case, i.e.,  "#ifdef  errno".
  8717.  
  8718.  
  8719.  187. Different OS/2 Libraries: DOSCALLS.LIB OS2.LIB API.LIB
  8720.  
  8721.  Product Version(s): 5.10   | 5.10
  8722.  Operating System:   MS-DOS | OS/2
  8723.  Flags: ENDUSER |
  8724.  Last Modified: 17-JAN-1989    ArticleIdent: Q37641
  8725.  
  8726.  Question:
  8727.  
  8728.  What are the differences between DOSCALLS.LIB, OS2.LIB, and API.LIB?
  8729.  
  8730.  Response:
  8731.  
  8732.  DOSCALLS.LIB has the OS/2 Version 1.00 systems calls in it.
  8733.  
  8734.  OS2.LIB is a superset of DOSCALLS.LIB, this library came with the
  8735.  OS/2 SDK not with the retail version of C 5.1. It has the OS/2
  8736.  Version 1.10 systems calls in it (PM calls have been added to the
  8737.  OS/2 Version 1.00 calls).
  8738.  
  8739.  API.LIB is the library used for programs that are going to be bound to
  8740.  run in both OS/2 and DOS. They are the FAPI ( Family API) routines.
  8741.  
  8742.  You can use OS2.LIB in place of DOSCALLS.LIB because it contains all
  8743.  of the routines. Only use API.LIB if you are binding.
  8744.  
  8745.  
  8746.  188. EMULATOR_TEXT and EMULATOR_DATA Segments in Small Model
  8747.  
  8748.  Product Version(s): 4.00 5.00 5.10 | 5.10
  8749.  Operating System:   MS-DOS         | OS/2
  8750.  Flags: ENDUSER | S_QUICKC
  8751.  Last Modified:  8-NOV-1988    ArticleIdent: Q37664
  8752.  
  8753.  Small-model C programs compiled with the floating-point emulator
  8754.  library (/FPi or /FPc option) may produce two segments of code and
  8755.  data each. If there are floating-point operations in your program, the
  8756.  compiler will generate these extra segments. The map file shows these
  8757.  segments as EMULATOR_TEXT and EMULATOR_DATA.
  8758.  
  8759.  EMULATOR_TEXT is the code segment for the emulator. In some cases,
  8760.  small-model programs can have two code segments. Because the code in
  8761.  the emulator only is accessed through far calls and interrupts, this
  8762.  is not a problem. Both EMULATOR_TEXT and EMULATOR_DATA are in separate
  8763.  segments from DGROUP and _TEXT in all memory models.
  8764.  
  8765.  
  8766.  189. cl /Fs Filename Fails to Generate Symbol Table on Error
  8767.  
  8768.  Product Version(s): 5.10   | 5.10
  8769.  Operating System:   MS-DOS | OS/2
  8770.  Flags: ENDUSER | docerr
  8771.  Last Modified:  8-NOV-1988    ArticleIdent: Q37665
  8772.  
  8773.  When compiling with the /Fs option to produce a source listing, it
  8774.  will provide you with tables for global and local symbols. However, if
  8775.  the compiler generates error messages, then a list file will not
  8776.  contain the symbol tables.
  8777.  
  8778.  
  8779.  190. Additional Causes of Error C2152
  8780.  
  8781.  Product Version(s): 5.00 5.10 | 5.00 5.10
  8782.  Operating System:   MS-DOS    | OS/2
  8783.  Flags: ENDUSER | S_QUICKC docerr
  8784.  Last Modified: 14-NOV-1988    ArticleIdent: Q37666
  8785.  
  8786.  Page 267 of the "Microsoft C 5.1 Optimizing Compiler User's Guide"
  8787.  (Page 337 of the "Microsoft QuickC Programmer's Guide") states that
  8788.  error C2152 (pointers to functions with different attributes) is
  8789.  caused when the following occurs:
  8790.  
  8791.     An attempt was made to assign a pointer to a function
  8792.     declared with one calling convention (cdecl, fortran, or
  8793.     pascal) to a pointer to a function declared with a
  8794.     different calling convention.
  8795.  
  8796.  This is correct, but incomplete. Additional causes are mixing near
  8797.  and far function pointers and mixing interrupt and non-interrupt
  8798.  function pointers.
  8799.  
  8800.  
  8801.  191. Error C2170 Identifier : Intrinsic Not Declared as a Function
  8802.  
  8803.  Product Version(s): 5.00 5.10 | 5.10
  8804.  Operating System:   MS-DOS    | OS/2
  8805.  Flags: ENDUSER | s_quickc s_error docerr
  8806.  Last Modified: 14-NOV-1988    ArticleIdent: Q37719
  8807.  
  8808.  The error below is from "Compilation-Error Messages" in the
  8809.  "Microsoft C Optimizing Compiler User's Guide," Section E.3.2, Page
  8810.  268. It is not documented in either the "Microsoft QuickC Compiler
  8811.  Programmer's Guide," or in the README.DOC file, for the Microsoft
  8812.  QuickC Compiler Versions 1.00 and 1.01.
  8813.  
  8814.  The following is the error:
  8815.  
  8816.  C2170       identifier : intrinsic not declared as a function
  8817.  
  8818.          You tried to use the intrinsic pragma for an item other
  8819.              than a function, or for a function that does not have an
  8820.              intrinsic form. (The section titled "Generating Intrinsic
  8821.              Functions" in Section 3.3.15 lists the functions that have
  8822.              intrinsic forms.)
  8823.  
  8824.  The section reference given in the error explanation is wrong. It is
  8825.  found in Section 3.3.13.1 beginning on Page 93 of the "Microsoft C
  8826.  Optimizing Compiler User's Guide."
  8827.  
  8828.  When the compiler encounters any of the errors listed in this section,
  8829.  it continues parsing the program (if possible) and outputs additional
  8830.  error messages. However, no object file is produced.
  8831.  
  8832.  
  8833.  192. Error C2172 Function : Actual Is Not a Pointer...
  8834.  
  8835.  Product Version(s): 5.00 5.10 | 5.10
  8836.  Operating System:   MS-DOS    | OS/2
  8837.  Flags: ENDUSER | s_quickc s_error
  8838.  Last Modified: 14-NOV-1988    ArticleIdent: Q37721
  8839.  
  8840.  The following error is from "Compilation-Error Messages" in the
  8841.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.2, Page
  8842.  339, and from "Compiler and Run-Time Errors -- New Messages" in the
  8843.  Microsoft C Optimizing Compiler file ERRMSG.DOC, on Version 5.00's
  8844.  Setup Disk and on Version 5.10's Compiler Disk 1, but not in the
  8845.  "Microsoft C Optimizing Compiler User's Guide" for those versions:
  8846.  
  8847.  C2172       function : actual is not a pointer, parameter number
  8848.  
  8849.              An attempt was made to pass a non-pointer argument to a
  8850.              function that expected a pointer. The given number
  8851.              indicates which argument was in error.
  8852.  
  8853.  When the compiler encounters any of the errors listed in this section,
  8854.  it continues parsing the program (if possible) and outputs additional
  8855.  error messages. However, no object file is produced.
  8856.  
  8857.  
  8858.  193. Error C2174 Function : Actual Has Type Void : Parameter...
  8859.  
  8860.  Product Version(s): 5.00 5.10 | 5.10
  8861.  Operating System:   MS-DOS    | OS/2
  8862.  Flags: ENDUSER | s_quickc s_error
  8863.  Last Modified: 14-NOV-1988    ArticleIdent: Q37723
  8864.  
  8865.  The following error is from "Compilation-Error Messages" in the
  8866.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.2, Page
  8867.  340, and from "Compiler and Run-Time Errors -- New Messages" in the
  8868.  Microsoft C Optimizing Compiler file ERRMSG.DOC, on Version 5.00's
  8869.  Setup Disk and on Version 5.10's Compiler Disk 1, but not in the
  8870.  "Microsoft C Optimizing Compiler User's Guide" for those versions:
  8871.  
  8872.  C2174       function : actual has type void : parameter number,
  8873.              parameter list number
  8874.  
  8875.              An attempt was made to pass a void argument to a function.
  8876.              Formal parameters and arguments to functions cannot have
  8877.              type void; however, they can have type void * (pointer
  8878.              to void). This error occurs in calls that return a pointer
  8879.              to a function. The first number indicates which argument
  8880.              was in error; the second number indicates which argument
  8881.              list contained the invalid argument.
  8882.  
  8883.  When the compiler encounters any of the errors listed in this section,
  8884.  it continues parsing the program (if possible) and outputs additional
  8885.  error messages. However, no object file is produced.
  8886.  
  8887.  
  8888.  194. Error C2173 Function : Actual Is Not a Pointer...
  8889.  
  8890.  Product Version(s): 5.00 5.10 | 5.10
  8891.  Operating System:   MS-DOS    | OS/2
  8892.  Flags: ENDUSER | s_quickc s_error
  8893.  Last Modified: 14-NOV-1988    ArticleIdent: Q37724
  8894.  
  8895.  The following error is from "Compilation-Error Messages" in the
  8896.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.2, Page
  8897.  339, and from "Compiler and Run-Time Errors -- New Messages" in the
  8898.  Microsoft C Optimizing Compiler file ERRMSG.DOC, on Version 5.00's
  8899.  Setup Disk and on Version 5.10's Compiler Disk 1, but not in the
  8900.  "Microsoft C Optimizing Compiler User's Guide" for those versions.
  8901.  
  8902.  C2173       function : actual is not a pointer : parameter number :
  8903.              parameterlist number
  8904.  
  8905.              An attempt was made to pass a non-pointer argument to a
  8906.              function that expected a pointer. This error occurs in
  8907.              calls that return a pointer to a function. The first
  8908.              number indicates which argument was in error; the second
  8909.              number indicates which argument list contained the invalid
  8910.              argument.
  8911.  
  8912.  When the compiler encounters any of the errors listed in this section,
  8913.  it continues parsing the program (if possible) and outputs additional
  8914.  error messages. However, no object file is produced.
  8915.  
  8916.  
  8917.  195. Error C2143 Syntax Error : Missing 'token1' before 'token2'
  8918.  
  8919.  Product Version(s): 5.00 5.10 | 5.10
  8920.  Operating System:   MS-DOS    | OS/2
  8921.  Flags: ENDUSER | s_quickc s_error
  8922.  Last Modified: 14-NOV-1988    ArticleIdent: Q37726
  8923.  
  8924.  The following error is from "Compilation-Error Messages" in the
  8925.  "Microsoft C Optimizing Compiler User's Guide," Section E.3.2, Page
  8926.  265, and in the "Microsoft QuickC Compiler Programmer's Guide,"
  8927.  Section D.1.2, Page 336:
  8928.  
  8929.  C2143       syntax error : missing 'token1' before 'token2'
  8930.  
  8931.              The compiler expected token1 to appear before token2. This
  8932.              message may appear if a required closing brace (}), right
  8933.              parenthesis ()), or semicolon (;) is missing.
  8934.  
  8935.  When the compiler encounters any of the errors listed in this section,
  8936.  it continues parsing the program (if possible) and outputs additional
  8937.  error messages. However, no object file is produced.
  8938.  
  8939.  This error can occur when a semicolon (;) is missing at the end of a
  8940.  function prototype. The following program demonstrates this:
  8941.  
  8942.  void foo(void)
  8943.  void main(void)
  8944.  {
  8945.  }
  8946.  
  8947.  When this code is compiled, the following errors occur:
  8948.  
  8949.  error C2085: 'main' : not in formal parameter list
  8950.  error C2143: syntax error : missing ';' before '{'
  8951.  
  8952.  With no semicolon to mark the end of the prototype, the compiler
  8953.  interprets the prototype as the start of a function definition, and
  8954.  the next line to follow the prototype as if it were the first
  8955.  declaration within a function definition.
  8956.  
  8957.  
  8958.  196. Error C2152 Identifier : Pointers to Functions...
  8959.  
  8960.  Product Version(s): 5.00 5.10 | 5.10
  8961.  Operating System:   MS-DOS    | OS/2
  8962.  Flags: ENDUSER | s_quickc s_error
  8963.  Last Modified: 14-NOV-1988    ArticleIdent: Q37727
  8964.  
  8965.  The following error is from "Compilation-Error Messages" in the
  8966.  "Microsoft C Optimizing Compiler User's Guide," Section E.3.2, Page
  8967.  267, and in the "Microsoft QuickC Compiler Programmer's Guide,"
  8968.  Section D.1.2, Page 337:
  8969.  
  8970.  C2152       identifier : pointers to functions with different
  8971.              attributes
  8972.  
  8973.              An attempt was made to assign a pointer to a function
  8974.              declared with one calling convention (cdecl, fortran, or
  8975.              pascal) to a pointer to a function declared with a
  8976.              different calling convention.
  8977.  
  8978.  When the compiler encounters any of the errors listed in this section,
  8979.  it continues parsing the program (if possible) and outputs additional
  8980.  error messages. However, no object file is produced.
  8981.  
  8982.  Additional causes for this error include mixing near and far function
  8983.  pointers and mixing interrupt and non-interrupt function pointers.
  8984.  
  8985.  
  8986.  197. Share Problems Documentation Error for open
  8987.  
  8988.  Product Version(s): 5.00   | 5.10
  8989.  Operating System:   MS-DOS | OS/2
  8990.  Flags: ENDUSER | docerr
  8991.  Last Modified: 14-NOV-1988    ArticleIdent: Q37758
  8992.  
  8993.  The important note on Page 446 of the "Microsoft Optimizing 5.1
  8994.  Compiler Run-Time Library Reference" manual has an error in the second
  8995.  possible work around described in the second paragraph of the note.
  8996.  
  8997.  "Another work around is to open the file with pmode set to S_IREAD and
  8998.  omode..." is incorrect. The word omode should be replaced with the
  8999.  word oflag.
  9000.  
  9001.  
  9002.  198. Emulator Math Operations in My DLL that Uses LLIBCDLL
  9003.  
  9004.  Product Version(s): 5.10   | 5.10
  9005.  Operating System:   MS-DOS | OS/2
  9006.  Flags: ENDUSER |
  9007.  Last Modified: 14-NOV-1988    ArticleIdent: Q37778
  9008.  
  9009.  Question:
  9010.  
  9011.  I am using LLIBCDLL.LIB for my DLL. This library is supposed to use
  9012.  the alternate math package; however, when I compile and link, it
  9013.  appears to get emulator instructions in the code and my DLL does not
  9014.  act correctly. Where are these emulator instructions coming from, and
  9015.  how do I get rid of them?
  9016.  
  9017.  Response:
  9018.  
  9019.  Most likely the problem is that you are not using the /FPa switch on
  9020.  the compile line. You need this switch or the compiler assumes the
  9021.  emulator math package (default) and puts emulator math commands in
  9022.  your code. When this emulator math code is linked with LLIBCDLL.LIB,
  9023.  which uses alternate math, it will not work correctly.
  9024.  
  9025.  
  9026.  199. Reading the ESC Key from the Keyboard with _gets
  9027.  
  9028.  Product Version(s): 5.10
  9029.  Operating System:   MS-DOS
  9030.  Flags: ENDUSER |
  9031.  Last Modified: 15-NOV-1988    ArticleIdent: Q38023
  9032.  
  9033.  When the ESC key is pressed when entering a keyboard string to be read
  9034.  with the run-time library function _gets, it clears the keyboard
  9035.  buffer, and the only characters that are read by the _gets function
  9036.  are those pressed after the ESC key.
  9037.  
  9038.  This is a DOS command line feature. The _gets function does not
  9039.  receive the input of the command line until the ENTER key is pressed.
  9040.  Pressing the ESC key clears the keyboard buffer. If you need to accept
  9041.  the ESC key stroke, use the _getc function.
  9042.  
  9043.  
  9044.  200. A Case where BUFF
  9045.  
  9046.  Product Version(s): 5.10   | 5.10
  9047.  Operating System:   MS-DOS | OS/2
  9048.  Flags: ENDUSER |
  9049.  Last Modified: 15-NOV-1988    ArticleIdent: Q38024
  9050.  
  9051.  When the variable buff has been declared in an assembly-language
  9052.  program, such as the following
  9053.  
  9054.          .data
  9055.          public buff
  9056.  _buff   db 200 dup (0xab)
  9057.          .data ends
  9058.  
  9059.  there is a difference between the two following C declarations:
  9060.  
  9061.     extern unsigned char buff[];
  9062.  
  9063.     extern unsigned *buff;
  9064.  
  9065.  The difference is that the first declaration says that there
  9066.  is a block of memory that is named buff; the second says
  9067.  that there is something called buff that is a pointer.
  9068.  
  9069.  This difference can be seen by referencing buff as follows:
  9070.  
  9071.     buff[x]
  9072.  
  9073.  If buff is declared as an array, the referencing is correct.
  9074.  
  9075.  However, if buff is declared as a pointer, the referencing is
  9076.  incorrect. The data pointed to by buff (ab in this example) is
  9077.  translated into a memory address, then x bytes is added to it
  9078.  generating an incorrect reference.
  9079.  
  9080.  
  9081.  201. Signed char Type Converted to int Type at Function Call
  9082.  
  9083.  Product Version(s): 4.00 5.00 5.10 | 5.10
  9084.  Operating System:   MS-DOS         | OS/2
  9085.  Flags: ENDUSER |
  9086.  Last Modified: 15-NOV-1988    ArticleIdent: Q38025
  9087.  
  9088.  Question :
  9089.  
  9090.  Any char value equal to or greater than 0x80 is printed with 0xff
  9091.  preceding it when I do the following:
  9092.  
  9093.  1. Declare an array of char and initialize it with hexadecimals.
  9094.  
  9095.  2. Later in the program, use printf to display the values of the
  9096.     array element.
  9097.  
  9098.  3. Use "%2x" as format string. (See sample program below.)
  9099.  
  9100.  Why does this behavior occur?
  9101.  
  9102.  Response:
  9103.  
  9104.  Use "unsigned char" to declare the array "bit", or use the /J compiler
  9105.  option to change the char type from its default of signed char to
  9106.  unsigned char.
  9107.  
  9108.  This is not a problem of Microsoft C Compiler. In the sample program
  9109.  below, the element of array "bits" has char type, which is a signed
  9110.  type in the Microsoft C compiler. In C when a variable is used as an
  9111.  actual argument in a function call, usual unary data type conversion is
  9112.  automatically performed before the argument is passed to the function.
  9113.  
  9114.  In particular, signed char type is converted to int type using sign
  9115.  extension (see the "Microsoft C Optimizing Compiler Language
  9116.  Reference" manual for data conversion rules.) Because signed char type
  9117.  can represent values from -128 to 127 (in our compiler -128 is not
  9118.  defined), and a negative value is represented in two's complement form,
  9119.  any hexadecimal number greater than 0x80, which is a negative value in
  9120.  signed char type, will be converted to signed int type in
  9121.  corresponding two's complement form.
  9122.  
  9123.  For example, 0x80 (-128) is converted to 0xff80; 0x81 (-127) is
  9124.  converted to 0xff81.
  9125.  
  9126.  When using "printf" with unsigned hexadecimal integer control
  9127.  character "%x", the values are displayed in its unsigned hexadecimal
  9128.  format. If "%d" is used, the values are displayed in signed decimal
  9129.  format.
  9130.  
  9131.  The following is a sample program:
  9132.  
  9133.  #include <stdio.h>
  9134.  char bits[8] = {0x80, 0x81, 0x91, 0x00, 0x7f, 0x20, 0x40, 0x08} ;
  9135.  main()
  9136.  {  int i ;
  9137.     for (i=0; i<8 ; i++)
  9138.        printf("%2x ", bits[i]) ;
  9139.     printf("\n") ;
  9140.     for (i=0; i<8 ; i++)
  9141.        printf("%d ", bits[i]) ;
  9142.  }
  9143.  
  9144.  Output :
  9145.    ff80 ff81 ff91 00 7f 20 08
  9146.    -128 -127 -111 0  127 32 8
  9147.  
  9148.  
  9149.  202. Minimum Range Values in the Include File limits.h
  9150.  
  9151.  Product Version(s): 5.10   | 5.10
  9152.  Operating System:   MS-DOS | OS/2
  9153.  Flags: ENDUSER | S_QUICKC
  9154.  Last Modified: 15-NOV-1988    ArticleIdent: Q38026
  9155.  
  9156.  Question:
  9157.  
  9158.  Why is the minimum value of CHAR and INT off by one in the include
  9159.  file limits.h?
  9160.  
  9161.  Response:
  9162.  
  9163.  This behavior occurs because there is no corresponding positive value
  9164.  for the SIGNED CHAR's minimum value. For example, the range of a
  9165.  SIGNED CHAR is -128 to 127. The range specified in limits.h is -127 to
  9166.  127. The range of a signed int is -32768 to 32767, but limits.h
  9167.  specifies the range as -32767 to 32767.
  9168.  
  9169.  If you were to take the absolute value of -128 with the ABS() function,
  9170.  you would expect to get +128. This is correct; however, you must
  9171.  ensure that you store the result in a variable that has a storage
  9172.  class that can represent the value.
  9173.  
  9174.  For example, it does not make sense, and is not possible, to take the
  9175.  absolute value of -128 and try and store it in a SIGNED CHAR. 127 is
  9176.  the maximum positive value for a this storage class.
  9177.  
  9178.  The return value from the ABS() function is undefined if you try
  9179.  to store the result in a storage class that cannot represent the
  9180.  value.
  9181.  
  9182.  
  9183.  203. Two's Complement
  9184.  
  9185.  Product Version(s): 4.00 5.00 5.10 | 5.10
  9186.  Operating System:   MS-DOS         | OS/2
  9187.  Flags: ENDUSER |
  9188.  Last Modified: 16-NOV-1988    ArticleIdent: Q38027
  9189.  
  9190.  Question:
  9191.  
  9192.  What is two's complement?
  9193.  
  9194.  Response:
  9195.  
  9196.  In most of the C compilers, including Microsoft C Compiler, negative
  9197.  values are represented internally in two's complement format. Two's
  9198.  complement can be obtained by negating each bit of the value, then
  9199.  adding 1. Performing two's complement twice generates the original
  9200.  value.
  9201.  
  9202.  The following is an example:
  9203.  
  9204.  Original value           | Two's complement
  9205.  -------------------------|------------------------------
  9206.  (dec)   (hex)  (binary)  | (dec)   (hex)   (binary)
  9207.  127     0x7f   01111111  | -127    0x81    10000001
  9208.  111     0x6f   01101111  | -111    0x91    10010001
  9209.  -111    0x91   10010001  | 111     0x6f    01101111
  9210.  
  9211.  
  9212.  204. Turning Off Cursor in Text Mode
  9213.  
  9214.  Product Version(s): 5.10
  9215.  Operating System:   MS-DOS
  9216.  Flags: ENDUSER | s_c
  9217.  Last Modified: 17-NOV-1988    ArticleIdent: Q38124
  9218.  
  9219.  Question:
  9220.  
  9221.  How do I turn off the cursor in text mode? I can do it in graphics
  9222.  mode but that doesn't work in text mode.
  9223.  
  9224.  Response:
  9225.  
  9226.  There is no function in the run-time library to do that; however, you
  9227.  can do it with a bios function call.
  9228.  
  9229.  Use INT 10 FUNCTION 1. Set the CH register to 20h and call the
  9230.  interrupt to turn off the cursor. The following is a sample program:
  9231.  
  9232.   #include <dos.h>
  9233.  
  9234.   void main(void)
  9235.   {
  9236.       union REGS regs;
  9237.  
  9238.       regs.h.ah = 1;
  9239.       regs.h.ch = 20;
  9240.       int86 ( 0x10, ®s, ®s );
  9241.  
  9242.   }
  9243.  
  9244.  
  9245.  205. SDK C Documentation Incorrect for memcpy
  9246.  
  9247.  Product Version(s): 4.50   | 5.10
  9248.  Operating System:   MS-DOS | OS/2
  9249.  Flags: ENDUSER | docerr
  9250.  Last Modified: 18-NOV-1988    ArticleIdent: Q38189
  9251.  
  9252.  Page 339 of the "Microsoft Operating System/2 Software Development
  9253.  Kit/ Microsoft C Optimizing Compiler Run-Time Library Reference"
  9254.  incorrectly states that the memcpy function ensures proper copying of
  9255.  source bytes to the destination if both regions overlap. Microsoft C
  9256.  Optimizing Compiler Versions 4.50 or later do not guarantee that
  9257.  source bytes in the overlapping area are copied before being
  9258.  overwritten.
  9259.  
  9260.  The memcpy function in Version 4.00 of the Microsoft C compiler
  9261.  ensures that copying worked for overlapping regions. Starting with the
  9262.  Microsoft C Compiler Version 4.50, this was no longer true. The OS/2
  9263.  SDK was first released with C Version 4.50 without the new Microsoft C
  9264.  run-time library reference documentation. When the OS/2 SDK package
  9265.  was updated to C Versions 5.00 and 5.10, the old Microsoft C run-time
  9266.  library reference was not updated. The separate retail packages of the
  9267.  Microsoft C Optimizing Compiler Versions 5.00 and 5.10 has the new C
  9268.  run-time library reference.
  9269.  
  9270.  The change was made because ANSI requires that the memmove function,
  9271.  not the memcpy function, be used to copy overlapping regions. Because
  9272.  no memmove function exists in the Microsoft C Compiler Version 4.00,
  9273.  and Microsoft follows ANSI standards, the function memcpy included
  9274.  overlapping checking. The added memmove function in C Version 5.00
  9275.  prompted the change in the memcpy function. The memmove was added to
  9276.  handle overlapping regions while memcpy (the old handler of overlapped
  9277.  regions) was implemented as the "fast" copy.
  9278.  
  9279.  
  9280.  206. C: _acrtused Must Be Defined When Not Including Start-Up Code
  9281.  
  9282.  Product Version(s): 5.00 5.10 | 5.10
  9283.  Operating System:   MS-DOS    | OS/2
  9284.  Flags: ENDUSER | s_quickc acrtused __acrtused ROM
  9285.  Last Modified: 26-JAN-1990    ArticleIdent: Q43646
  9286.  
  9287.  The object modules created by the Microsoft C Optimizing Compiler,
  9288.  Versions 5.10 and earlier, contain a reference to the variable
  9289.  _acrtused. This variable causes the linker to bring in the C start-up
  9290.  code. To not link the C start-up code, it is necessary to define
  9291.  _acrtused as follows:
  9292.  
  9293.     int _acrtused = 0;
  9294.  
  9295.  
  9296.  207. P_NOWAIT Is Not Implemented in DOS Version 4.00
  9297.  
  9298.  Product Version(s): 5.00   | 5.10
  9299.  Operating System:   MS-DOS | OS/2
  9300.  Flags: ENDUSER |
  9301.  Last Modified: 18-NOV-1988    ArticleIdent: Q38191
  9302.  
  9303.  The include file process.h states that P_NOWAIT is enabled in DOS
  9304.  Version 4.00. This is incorrect. P_NOWAIT is NOT enabled in the
  9305.  current version of DOS Version 4.00. P_NOWAIT is a modeflag as used in
  9306.  SPAWNxx functions. P_NOWAIT is used to continue executing the parent
  9307.  process concurrently with the child process. P_NOWAIT is implemented in
  9308.  OS/2.
  9309.  
  9310.  Original DOS Version 4.00 was a multitasking, real-mode only MS-DOS.
  9311.  The limitations of the real-mode environment made DOS Version 4.00 a
  9312.  specialized product. Although MS-DOS Version 4.00 supports full preemtive
  9313.  multitasking, system memory is limited to the 640 kilobytes available
  9314.  in real mode. This means that all processes have to fit into the
  9315.  single 640-kilobyte memory area. Because of these restrictions, MS-DOS
  9316.  Version 4.00 was not intended for general release, but as a platform
  9317.  for specific OEMs to support extended architectures. Therefore, MS-DOS
  9318.  Version 4.00 was released as a special OEM product only.
  9319.  
  9320.  
  9321.  208. Run-Time Functions remove and unlink both Delete a File
  9322.  
  9323.  Product Version(s): 5.00 5.10 | 5.10
  9324.  Operating System:   MS-DOS    | OS/2
  9325.  Flags: ENDUSER |
  9326.  Last Modified: 21-NOV-1988    ArticleIdent: Q38198
  9327.  
  9328.  The Microsoft C Optimizing Compiler Run-Time Library contains two
  9329.  routines that delete a file. The remove function is documented on Page
  9330.  490, and the unlink function is documented on Page 628 of the
  9331.  "Microsoft C Optimizing Compiler Run-Time Library Reference" manual.
  9332.  Both routines take the same argument and perform the same operation.
  9333.  
  9334.  The unlink function exists for Unix/XENIX compatibility. This
  9335.  information is documented in Sections B.2.1, B.2.3, and B.5.4 of the
  9336.  same manual.
  9337.  
  9338.  
  9339.  209. Why pointer1++ = pointer2 Is Illegal
  9340.  
  9341.  Product Version(s): 5.00 5.10 | 5.10
  9342.  Operating System:   MS-DOS    | OS/2
  9343.  Flags: ENDUSER |
  9344.  Last Modified: 21-NOV-1988    ArticleIdent: Q38218
  9345.  
  9346.  Question:
  9347.  
  9348.  Why is the following statement
  9349.  
  9350.     pointer1++ = pointer2 ;
  9351.  
  9352.  illegal, causing error 2106 : left operand must be lvalue,
  9353.  when the following statement is legal?
  9354.  
  9355.     *pointer1++ = *pointer2 ;
  9356.  
  9357.  Both pointer1 and pointer2 are declared as pointers to the same type.
  9358.  
  9359.  Response:
  9360.  
  9361.  Because the post-increment operator ++ has higher precedence than the
  9362.  assignment operator =, the following statement
  9363.  
  9364.     pointer1++ = pointer2 ;
  9365.  
  9366.  is equivalent to the following statement:
  9367.  
  9368.     (pointer1++) = pointer2 ;
  9369.  
  9370.  As defined by the post-increment operation, the result of evaluating
  9371.  the expression (pointer1++) is NOT a lvalue. So (pointer1++) cannot
  9372.  be used as a left operand of the assignment operator.
  9373.  
  9374.  However, a statement such as the following, which is equivalent to
  9375.  *(pointer1++) = *pointer2 ;, is legal:
  9376.  
  9377.      *pointer1++ = *pointer2 ;
  9378.  
  9379.  This statement is legal because although (pointer1++) is not a lvalue,
  9380.  it can be used for indirection and *(pointer1++) is a lvalue.
  9381.  
  9382.  It is very important to understand the difference between the value of
  9383.  the expression (pointer1++) and the value of pointer1. Although
  9384.  (pointer1++) has higher precedence in the above statements, the result
  9385.  of evaluating (pointer1++) has the old value that pointer1 had before
  9386.  the evaluation of the expression (pointer1++). Because of the side
  9387.  effect of the post-increment operator, the evaluation of (pointer1++)
  9388.  causes the value of pointer1 to be incremented by 1 only after the
  9389.  rest of the statement has been evaluated. In other words, as an
  9390.  address, (pointer1++) points to the same memory location as pointer1
  9391.  used to. Therefore, *pointer1++ or *(pointer1++) represents the same
  9392.  object as *pointer1 used to.
  9393.  
  9394.  The following example has the effect of assigning "a" to memory
  9395.  offset location 0x100, then incrementing ptr1 to point to memory
  9396.  offset 0x101:
  9397.  
  9398.  char * ptr1 = 0x100; /* ptr1 points to memory offset 0x100
  9399.                          in the current data segment
  9400.                          for small or medium memory models */
  9401.  *ptr1++ = 'a';
  9402.  
  9403.  
  9404.  210. /Au Switch Loads DS for Each Function, Not Module
  9405.  
  9406.  Product Version(s): 5.00 5.10 | 5.00 5.10
  9407.  Operating System:   MS-DOS    | OS/2
  9408.  Flags: ENDUSER | docerr
  9409.  Last Modified: 21-NOV-1988    ArticleIdent: Q38221
  9410.  
  9411.  Page 1 of the the "Microsoft C 5.10 (and 5.00) Quick Reference Guide"
  9412.  states the following under the /Au switch:
  9413.  
  9414.     "SS not equal to DS; DS loaded for each module"
  9415.  
  9416.  This should read as follows:
  9417.  
  9418.     "SS not equal to DS; DS loaded for each function"
  9419.  
  9420.  This message is correctly noted on Page 154 of the "Microsoft C 5.1
  9421.  Optimizing Compiler User's Guide."
  9422.  
  9423.  
  9424.  211. Error C1053 Compiler Limit : Struct/union Nesting
  9425.  
  9426.  Product Version(s): 5.00 5.10 | 5.10
  9427.  Operating System:   MS-DOS    | OS/2
  9428.  Flags: ENDUSER | s_quickc s_error docerr
  9429.  Last Modified: 19-DEC-1988    ArticleIdent: Q38225
  9430.  
  9431.  The following error is from "Fatal-Error Messages" in the "Microsoft C
  9432.  Optimizing Compiler User's Guide," Section E.3.1, Page 250, and in the
  9433.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
  9434.  319:
  9435.  
  9436.  C1053       compiler limit : struct/union nesting
  9437.  
  9438.              Structure and union definitions were nested to more than
  9439.              10 levels.
  9440.  
  9441.  The error message and explanation given for C1053 in the "Microsoft
  9442.  QuickC Compiler Programmer's Guide" is incorrect. It has been switched
  9443.  with the message and description for C1027.
  9444.  
  9445.  The compiler cannot recover from a fatal error; it terminates after
  9446.  printing the error message.
  9447.  
  9448.  
  9449.  212. Error C1015 Cannot Open Include File 'filename'
  9450.  
  9451.  Product Version(s): 5.00 5.10 | 5.10
  9452.  Operating System:   MS-DOS    | OS/2
  9453.  Flags: ENDUSER | s_quickc s_error
  9454.  Last Modified: 30-NOV-1988    ArticleIdent: Q38266
  9455.  
  9456.  The error below is from "Fatal-Error Messages" in the "Microsoft
  9457.  QuickC Compiler Programmer's Guide," Section D.1.1, Page 315, and in
  9458.  the file ERRMSG.DOC found on the Compiler Disk 1 for Microsoft C
  9459.  Optimizing Compiler Version 5.10 and on the Setup Disk for Version
  9460.  5.00. It is not in the "Microsoft C Optimizing Compiler User's Guide."
  9461.  
  9462.  The following is the error:
  9463.  
  9464.  C1015       cannot open include file 'filename'
  9465.  
  9466.              The given file either did not exist, could not be opened,
  9467.              or was not found. Make sure your environment settings are
  9468.              valid and that you have given the correct path name for
  9469.              the file.
  9470.  
  9471.  The compiler cannot recover from a fatal error; it terminates after
  9472.  printing the error message.
  9473.  
  9474.  Some causes of this error include the following:
  9475.  
  9476.  1. Incorrectly set environment variables, especially TMP and INCLUDE.
  9477.     This error can occur if the INCLUDE environment variable has not
  9478.     been set correctly for your include file directory, or if spaces or
  9479.     other syntax errors are in the setting.
  9480.  
  9481.  2. Improper file handles setting. If the files= line in CONFIG.SYS is
  9482.     not high enough, this error will occur. If not set at all, the
  9483.     default is usually 8, which is too few. If it is set to greater
  9484.     than 20 and the DOS version cannot support that number, it will
  9485.     default to 8. File handles will typically be used during
  9486.     compilation and linkage by the CL driver, the compiler passes, the
  9487.     C source code file, the include files, the linker, libraries, and
  9488.     temporary files created by the compiler or linker.
  9489.  
  9490.  
  9491.  213. Error C1033 Cannot Open Assembly-Language Output 'filename'
  9492.  
  9493.  Product Version(s): 5.00 5.10 | 5.10
  9494.  Operating System:   MS-DOS    | OS/2
  9495.  Flags: ENDUSER | s_quickc s_error
  9496.  Last Modified: 30-NOV-1988    ArticleIdent: Q38267
  9497.  
  9498.  The following error is from "Fatal-Error Messages" in the
  9499.  "Microsoft C Optimizing Compiler User's Guide," Section E.3.1, Page
  9500.  247, and in the "Microsoft QuickC Compiler Programmer's Guide,"
  9501.  Section D.1.1, Page 316:
  9502.  
  9503.  C1033       cannot open assembly-language output file 'filename'
  9504.  
  9505.              One of the conditions listed under error message C1032
  9506.              prevents the given file from being opened.
  9507.  
  9508.  The compiler cannot recover from a fatal error; it terminates after
  9509.  printing the error message.
  9510.  
  9511.  The following is the information listed under error message C1032:
  9512.  
  9513.     One of the following statements about the file name or path name
  9514.     given (filename) is true:
  9515.  
  9516.     1.  The given name is not valid.
  9517.  
  9518.      2.  The file with the given name cannot be opened for lack of
  9519.          space.
  9520.  
  9521.     3.  A read-only file with the given name already exists.
  9522.  
  9523.  
  9524.  214. Error C1034 Cannot Open Source File 'filename'
  9525.  
  9526.  Product Version(s): 5.00 5.10 | 5.10
  9527.  Operating System:   MS-DOS    | OS/2
  9528.  Flags: ENDUSER | s_quickc s_error
  9529.  Last Modified: 30-NOV-1988    ArticleIdent: Q38268
  9530.  
  9531.  The following error is from "Fatal-Error Messages" in the "Microsoft C
  9532.  Optimizing Compiler User's Guide," Section E.3.1, Page 247, and in the
  9533.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
  9534.  316:
  9535.  
  9536.  C1034       cannot open source file 'filename'
  9537.  
  9538.              One of the conditions listed under error message C1032
  9539.              prevents the given file from being opened.
  9540.  
  9541.  The compiler cannot recover from a fatal error; it terminates after
  9542.  printing the error message.
  9543.  
  9544.  The following is the information listed under error message C1032:
  9545.  
  9546.              One of the following statements about the file name or
  9547.              path name given (filename) is true:
  9548.  
  9549.                 1.  The given name is not valid.
  9550.  
  9551.                 2.  The file with the given name cannot be opened for
  9552.                     lack of space.
  9553.  
  9554.                 3.  A read-only file with the given name already
  9555.                     exists.
  9556.  
  9557.  
  9558.  215. Error C1036 Cannot Open Source Listing File 'filename'
  9559.  
  9560.  Product Version(s): 5.00 5.10 | 5.10
  9561.  Operating System:   MS-DOS    | OS/2
  9562.  Flags: ENDUSER | s_quickc s_error
  9563.  Last Modified: 30-NOV-1988    ArticleIdent: Q38269
  9564.  
  9565.  The following error is from "Fatal-Error Messages" in the "Microsoft C
  9566.  Optimizing Compiler User's Guide," Section E.3.1, Page 248, and in the
  9567.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
  9568.  316:
  9569.  
  9570.  C1036       cannot open source listing file 'filename'
  9571.  
  9572.              One of the conditions listed under error message C1032
  9573.              prevents the given file from being opened.
  9574.  
  9575.  The compiler cannot recover from a fatal error; it terminates after
  9576.  printing the error message.
  9577.  
  9578.  The following is the information listed under error message C1032:
  9579.  
  9580.     One of the following statements about the file name or path name
  9581.     given (filename) is true:
  9582.  
  9583.     1.  The given name is not valid.
  9584.  
  9585.     2.  The file with the given name cannot be opened for lack of
  9586.         space.
  9587.  
  9588.     3.  A read-only file with the given name already exists.
  9589.  
  9590.  
  9591.  216. Error C1037 Cannot Open Object File 'filename'
  9592.  
  9593.  Product Version(s): 5.00 5.10 | 5.10
  9594.  Operating System:   MS-DOS    | OS/2
  9595.  Flags: ENDUSER | s_quickc s_error
  9596.  Last Modified: 30-NOV-1988    ArticleIdent: Q38270
  9597.  
  9598.  The following error is from "Fatal-Error Messages" in the "Microsoft C
  9599.  Optimizing Compiler User's Guide," Section E.3.1, Page 248, and in the
  9600.  "Microsoft QuickC Compiler Programmer's Guide," Section D.1.1, Page
  9601.  317:
  9602.  
  9603.  C1037       cannot open object file 'filename'
  9604.  
  9605.              One of the conditions listed under error message C1032
  9606.              prevents the given file from being opened.
  9607.  
  9608.  The compiler cannot recover from a fatal error; it terminates after
  9609.  printing the error message.
  9610.  
  9611.  The following is the information listed under error message C1032:
  9612.  
  9613.     One of the following statements about the file name or path name
  9614.     given (filename) is true:
  9615.  
  9616.     1.  The given name is not valid.
  9617.  
  9618.     2.  The file with the given name cannot be opened for lack of
  9619.         space.
  9620.  
  9621.     3.  A read-only file with the given name already exists.
  9622.  
  9623.  
  9624.  217. Error C1059 Out of Near Heap Space
  9625.  
  9626.  Product Version(s): 5.00 5.10 | 5.10
  9627.  Operating System:   MS-DOS | OS/2
  9628.  Flags: ENDUSER | s_quickc s_error
  9629.  Last Modified: 30-NOV-1988    ArticleIdent: Q38271
  9630.  
  9631.  The following error is from "Fatal-Error Messages" in (1) the
  9632.  "Microsoft C Optimizing Compiler User's Guide," Section E.3.1, Page
  9633.  250, and in (2) the "Microsoft QuickC Compiler Programmer's Guide,"
  9634.  Section D.1.1, Page 319:
  9635.  
  9636.  C1059       out of near heap space
  9637.  
  9638.  (1)         The compiler has run out of storage for items that it
  9639.              stores in the "near" (default data segment) heap. This
  9640.              usually means that your program has too many symbols or
  9641.              complex expressions. To correct the problem, divide the
  9642.              file into several smaller source files, or break
  9643.              expressions into smaller subexpressions.
  9644.  
  9645.  (2)         The compiler ran out of storage for items that it stores
  9646.              in the "near" (default data segment) heap.
  9647.  
  9648.  The compiler cannot recover from a fatal error; it terminates after
  9649.  printing the error message.
  9650.  
  9651.  The following is from "Part 2: Notes for the Microsoft C Optimizing
  9652.  Compiler User's Guide" in the README.DOC file on Compiler Disk 1 for
  9653.  Microsoft C Version 5.10. A similar section is found in the README
  9654.  file on the Setup Disk for Version 5.00.
  9655.  
  9656.  This release includes an alternate form of compiler pass 1 named
  9657.  C1L.EXE. This compiler pass can be used to compile programs that get
  9658.  the error message "out of near heap space". Invoke C1L.EXE by entering
  9659.  the CL command with the /B1 <path> option, as follows:
  9660.  
  9661.     cl /B1 <path>\c1l.exe <sourcefile>.c
  9662.  
  9663.  In the preceding command, <path> is the path (including drive and
  9664.  directory) where C1L.EXE resides, and <sourcefile> is the name of the
  9665.  C source file you want to compile.
  9666.  
  9667.  
  9668.  218. Example Incorrect on Page 373 of C Run-Time Library Reference
  9669.  
  9670.  Product Version(s): 5.00 5.10
  9671.  Operating System:   MS-DOS
  9672.  Flags: ENDUSER | docerr
  9673.  Last Modified: 22-NOV-1988    ArticleIdent: Q38283
  9674.  
  9675.  The example for intdosx on Page 373 of the "Microsoft C 5.1 Optimizing
  9676.  Compiler Run-Time Library Reference" is incorrect.
  9677.  
  9678.  To get the example to work correctly, the line that reads
  9679.  
  9680.     char far *dir = "\newdir";   /* Directory to create */
  9681.  
  9682.  must be changed to read as follows:
  9683.  
  9684.     char far *dir = "\\newdir";  /* Directory to create */
  9685.  
  9686.  The backslash character \ in a C string is interpreted as part of an
  9687.  escape code. To actually represent the backslash character for a
  9688.  file's path, use two consecutive backslashes.
  9689.  
  9690.  
  9691.  219. 80386 and 80387 Instruction Set
  9692.  
  9693.  Product Version(s): 5.00 5.10 | 5.10
  9694.  Operating System:   MS-DOS    | OS/2
  9695.  Flags: ENDUSER | h_fortran s_pascal s_quickc
  9696.  Last Modified:  7-DEC-1988    ArticleIdent: Q38284
  9697.  
  9698.  Question:
  9699.  
  9700.  According to the "Microsoft C 5.1 Optimizing Compiler User's Guide,"
  9701.  you can generate 80286 and 80287 instructions with your high-level
  9702.  language compilers. Can I also use the 80386 and 80387 instruction
  9703.  set?
  9704.  
  9705.  Response:
  9706.  
  9707.  You can use the 80386 and 80387 chips. However, none of our products
  9708.  generate true 80386 code, or use 32-bit addressing. Although our
  9709.  compilers do not generate specific 80386 or 80387 code, the code which
  9710.  is generated will run faster than on a 80286 and 80287.
  9711.  
  9712.  
  9713.  220. Detecting Presence of 80x87 Math Coprocessor
  9714.  
  9715.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  9716.  Operating System:   MS-DOS              | OS/2
  9717.  Flags: ENDUSER | SR# G881027-5369 8087 80287 80387 87 /FPc
  9718.  Last Modified: 30-NOV-1988    ArticleIdent: Q38285
  9719.  
  9720.  Question:
  9721.  
  9722.  My Microsoft C program is compiled with the /FPi (floating-point
  9723.  emulator) option. I would like to warn the user if they are running it
  9724.  on a machine that has no math coprocessor. Is there any way to detect
  9725.  if an 80x87 is currently being used by the floating-point libraries?
  9726.  
  9727.  Response:
  9728.  
  9729.  There is no direct way to query the Microsoft C floating-point
  9730.  libraries as to whether or not they're using a math coprocessor. If
  9731.  you compile /FPi, you're telling the compiler you don't want to have
  9732.  to worry about whether or not a coprocessor is present. Consequently,
  9733.  the compiler generates code that will do the following:
  9734.  
  9735.  1. Check to see if a 80x87 coprocessor is present.
  9736.  
  9737.  2. If so, use it.
  9738.  
  9739.  3. If not, emulate it with software routines.
  9740.  
  9741.  There is nothing in this algorithm to tell your program what it found.
  9742.  The only way you'll know it's emulating the coprocessor is by
  9743.  observing how slowly your program runs.
  9744.  
  9745.  If you really need to know whether a coprocessor is present, you'll
  9746.  have to test it yourself. For more information on how to test for the
  9747.  presence of an 80x87 coprocessor, please consult Intel's "80286 and
  9748.  80287 Programmer's Reference Manual," Pages 3-2 and 3-3 (in the 2nd
  9749.  half of the book). This section is titled "System-Level Numeric
  9750.  Programming," and states that your program can detect the presence of
  9751.  the 80287 NPX. It then gives an assembly-language example that works
  9752.  correctly for both 8086- and 80286-based machines.
  9753.  
  9754.  Here is how you could use this routine in your program:
  9755.  
  9756.  1. During initialization of your program, call the short Intel routine
  9757.     to see if a coprocessor is present.
  9758.  
  9759.  2. If there is a coprocessor, proceed normally.
  9760.  
  9761.  3. If there is no coprocessor, put up a message box explaining the
  9762.     following to the user:
  9763.  
  9764.     "Your computer lacks a coprocessor, but <my_app> will emulate it in
  9765.     software; this emulation will slow down the calculations that
  9766.     <my_app> needs to perform. To increase the performance of
  9767.     <my_app>, as well as other programs, add a numeric coprocessor to
  9768.     your system."
  9769.  
  9770.  4. Proceed with your program as you normally would. The C run-time
  9771.     libraries will automatically adjust for the presence or lack of a
  9772.     80x87.
  9773.  
  9774.  
  9775.  221. Cannot Define Preprocessor Directives with #define
  9776.  
  9777.  Product Version(s): 4.00 5.00 5.10 | 5.10
  9778.  Operating System:   MS-DOS         | OS/2
  9779.  Flags: ENDUSER | S_QUICKC
  9780.  Last Modified: 28-NOV-1988    ArticleIdent: Q38291
  9781.  
  9782.  The Microsoft C Compiler does not allow a "#define" statement to
  9783.  define another preprocessor directive. Although the preprocessor
  9784.  output option ( /P or /E ) generates the desired expansion, the
  9785.  Microsoft C Compiler Version 5.10 generates the following error
  9786.  messages when compiling the code below:
  9787.  
  9788.     error C2014: preprocessor command must start as first non-whitespace
  9789.     error C2054: expected '(' to follow 'define'
  9790.     error C2061: syntax error : identifier 'MAX'
  9791.  
  9792.  The following code demonstrates the problem:
  9793.  
  9794.  #define A( x )      x##define       MAX     100
  9795.  
  9796.  A( # )
  9797.  /*
  9798.      Preprocessor output expands A( # ) to be:
  9799.  #define       MAX     100
  9800.  */
  9801.  
  9802.  char w[ MAX ];
  9803.  void main(void);
  9804.  void main()
  9805.  {
  9806.  w[ 0 ] = w[ MAX ];
  9807.  }
  9808.  
  9809.  
  9810.  222. wait and cwait Are for Protected Mode
  9811.  
  9812.  Product Version(s): 5.10   | 5.10
  9813.  Operating System:   MS-DOS | OS/2
  9814.  Flags: ENDUSER |
  9815.  Last Modified:  7-DEC-1988    ArticleIdent: Q38293
  9816.  
  9817.  Page 556 of the "Microsoft C 5.1 Optimizing Compiler User's Guide"
  9818.  states that to obtain the exit code for an asynchronous spawned
  9819.  process, you must call the wait or cwait function and specify the
  9820.  process ID.
  9821.  
  9822.  Wait, Cwait, and asynchronous spawns can only occur in protected mode.
  9823.  
  9824.  The wait function suspends the calling process until any of the
  9825.  caller's immediate child processes terminate. If all of the caller's
  9826.  child processes have terminated before it calls the wait function, the
  9827.  function returns immediately.
  9828.  
  9829.  The cwait function suspends the calling process until the specified
  9830.  child process terminates.
  9831.  
  9832.  For more information, refer to the "Microsoft C 5.1 Optimizing
  9833.  Compiler User's Guide" Update Pages 30 and 48.
  9834.  
  9835.  
  9836.  223. Overwriting End of HALLOC Causes Crash at Termination
  9837.  
  9838.  Product Version(s): 5.00 5.10 | 5.00 5.10
  9839.  Operating System:   MS-DOS    | OS/2
  9840.  Flags: ENDUSER |
  9841.  Last Modified: 12-DEC-1988    ArticleIdent: Q38294
  9842.  
  9843.  The following message appearing at the termination of a program can be
  9844.  caused by overwriting past the end of a block of memory allocated by
  9845.  the halloc function:
  9846.  
  9847.     Memory allocation error: Cannot load command.com
  9848.  
  9849.  The bytes following a halloc'd block are used by DOS for keeping
  9850.  track of memory allocation, and DOS may be unable to load command.com
  9851.  upon completion of your process if this area is corrupted.
  9852.  
  9853.  This error can also conceivably be caused by overwriting blocks of
  9854.  memory allocated by other functions such as malloc, _nmalloc, and _fmalloc.
  9855.  
  9856.  
  9857.  224. How the Null Character Is Handled by Printf Functions.
  9858.  
  9859.  Product Version(s): 4.00 5.00 5.10 | 4.00 5.00 5.10
  9860.  Operating System:   MS-DOS         | OS/2
  9861.  Flags: ENDUSER | S_QuickC
  9862.  Last Modified: 28-NOV-1988    ArticleIdent: Q38296
  9863.  
  9864.  When the C run-time functions printf, fprintf, or sprintf encounter
  9865.  the character-conversion specifier %c in their format-control string,
  9866.  they will convert the corresponding argument of int type to unsigned
  9867.  char type and write the resulting value to output. Therefore, if the
  9868.  argument is a NULL character, the value 0 (not the character "0") is
  9869.  written to the output.
  9870.  
  9871.  The output can be stdout, a file (with fprintf) or a string (with
  9872.  sprintf). In case of stdout, the NULL character is ignored by the
  9873.  display device. In the case of string, the NULL character will be
  9874.  interpreted as a terminator character when the resulting string is
  9875.  used later in the program.
  9876.  
  9877.  The output of the following program is the result of expected
  9878.  behavior:
  9879.  
  9880.  #include <stdio.h>
  9881.  char buffer[30] ;
  9882.  main()
  9883.  {
  9884.  printf("Before,%c,After\n", '\0') ;
  9885.  sprintf(buffer, "Before,%c,After\n", '\0') ;
  9886.  printf(buffer) ;
  9887.  }
  9888.  /* end of sample program */
  9889.  
  9890.  Output :
  9891.  
  9892.  Before,,After
  9893.  Before,
  9894.  
  9895.  
  9896.  225. Spawn Will Not Pass Redirection to Child
  9897.  
  9898.  Product Version(s): 5.10
  9899.  Operating System:   MS-DOS
  9900.  Flags: ENDUSER | SR# S880925-1
  9901.  Last Modified: 12-DEC-1988    ArticleIdent: Q38308
  9902.  
  9903.  Question:
  9904.  
  9905.  When using the program below to spawn sort.exe, it seems that "sort"
  9906.  starts, but then sits there doing nothing. The behavior is similar to
  9907.  starting "sort" from the DOS prompt without any arguments.
  9908.  
  9909.  The following program demonstrates the problem:
  9910.  
  9911.  #include <stdio.h>
  9912.  #include <process.h>
  9913.  main()
  9914.  {
  9915.          char *args[6] ;
  9916.          args[0] = "sort" ;
  9917.          args[1] = "<" ;
  9918.          args[2] = "infile.dat" ; /* exists */
  9919.          args[3] = ">" ;         /* direct output to a disk file */
  9920.          args[4] = "outfile.dat" ;
  9921.          args[5] = NULL ;
  9922.  
  9923.          spawnvp (P_WAIT, "sort.exe", args) ;
  9924.  }
  9925.  
  9926.  Why doesn't this work correctly? What can I do about it?
  9927.  
  9928.  Response:
  9929.  
  9930.  Because COMMAND.COM, and NOT the EXEC loader, handles indirection,
  9931.  this is the expected behavior. Child processes inherit the handles of
  9932.  their parents; therefore, to redirect the input and output of the
  9933.  child you first change the definitions of STDIN and STDOUT in the
  9934.  parent process. The proper way to redirect input for a filter is
  9935.  described starting on Page 441 of the "MS-DOS Encyclopedia," along with
  9936.  a complete MASM example. Note: the dup and dup2 functions in the C
  9937.  Version 5.10 run-time library are the same as the INT 21h functions 45h
  9938.  and 46h, respectively.
  9939.  
  9940.  There also are partial examples of this technique on Page 230 of the
  9941.  "Microsoft C Version 5.10 Run-Time Library Reference" manual and on
  9942.  Page 353 of "Advanced MS-DOS Programming" (by Duncan, published by
  9943.  Microsoft Press).
  9944.  
  9945.  It is possible to use freopen() to redefine STDIN and STDOUT; however,
  9946.  doing so loses any redirection that may have been performed on the
  9947.  parent process.
  9948.  
  9949.  The easiest workaround is to use the system function to spawn a copy
  9950.  of COMMAND.COM that runs SORT.EXE, as follows:
  9951.  
  9952.     system("sort.exe <infile.dat >outfile.dat");
  9953.  
  9954.  
  9955.  226. Attributes in Hercules Graphics Mode
  9956.  
  9957.  Product Version(s): 5.10
  9958.  Operating System:   MS-DOS
  9959.  Flags: ENDUSER | s_quickc
  9960.  Last Modified: 19-DEC-1988    ArticleIdent: Q38312
  9961.  
  9962.  Problem:
  9963.  
  9964.  I'm using a Hercules graphics adapter in graphics mode and I would
  9965.  like to do high-intensity "bold" graphics, but I can't seem to get it
  9966.  to work correctly.
  9967.  
  9968.  Response:
  9969.  
  9970.  Using the Hercules graphics adapter in graphics mode, each pixel maps
  9971.  to only 1 bit in memory. Because there is only 1 bit, that pixel can
  9972.  only be on or off. In Hercules graphics mode, there is no facility for
  9973.  attributes such as high-intensity, blinking, reverse, or underline.
  9974.  
  9975.  In Hercules graphics mode, the only way to get blinking, reverse, and
  9976.  underline is for your program to manipulate or turn on and off each
  9977.  pixel. High-intensity will not be possible.
  9978.  
  9979.  If you put the adapter into Text mode, you can use all of these
  9980.  attributes freely.
  9981.  
  9982.  
  9983.  227. C Setup Gives Error U2155 When Building Libraries
  9984.  
  9985.  Product Version(s): 5.10   | 5.10
  9986.  Operating System:   MS-DOS | OS/2
  9987.  Flags: ENDUSER | S_LIB
  9988.  Last Modified: 15-JAN-1990    ArticleIdent: Q38319
  9989.  
  9990.  Problem:
  9991.  
  9992.  When installing Optimizing C, I get the following error:
  9993.  
  9994.     LIB : error U2155: <path> : module not in library; ignored
  9995.  
  9996.  Response:
  9997.  
  9998.  Most likely, this is caused by having a dash (-) embedded in the path
  9999.  specified as the combined libraries destination. Restart SETUP and do
  10000.  not include a dash in the library path.
  10001.  
  10002.  This is a problem with LIB.EXE.
  10003.  
  10004.  LIB cannot handle the "-" (hyphen, dash) character embedded in a
  10005.  directory/file name. Instead, it interprets the dash as the extraction
  10006.  operator giving rise to error U2155. The hyphen is a legal character
  10007.  for DOS file and directory names and many people use it (for example,
  10008.  MS-C for the C directory.) In this example, LIB will terminate with
  10009.  the following cryptic message:
  10010.  
  10011.     U2155:   C:\MS-C\MLIBCE.LIB  module not in library (ms.obj)
  10012.  
  10013.  The message is dependent upon the directory/file name used, but the
  10014.  symptom is always the same: module not in library, invalid object
  10015.  module, object file not found, etc.
  10016.  
  10017.  Note: this error can occur in situations other than setting up the
  10018.  compiler. Anytime you pass a directory/file name that contains a
  10019.  hyphen, you can cause this behavior.
  10020.  
  10021.  
  10022.  228. _Fheapwalk Does Not Check the Near Heap
  10023.  
  10024.  Product Version(s): 5.10   | 5.10
  10025.  Operating System:   MS-DOS | OS/2
  10026.  Flags: ENDUSER | S_QuickC
  10027.  Last Modified: 30-NOV-1988    ArticleIdent: Q38327
  10028.  
  10029.  The HeapWalk routines are provided as an aid in debugging heap-related
  10030.  problems in programs. In large-, huge-, and compact-memory models
  10031.  _heapwalk will map onto the function _fheapwalk. In small- and
  10032.  medium-memory models, it maps onto function _nheapwalk. The _fheapwalk
  10033.  function will not check or examine the near heap in the default data
  10034.  segement while _nheapwalk will examine only the near heap.
  10035.  
  10036.  Because _fheapwalk will not check the near heap, you should not assume
  10037.  that the HeapWalk routine will always reflect information about all
  10038.  your pointers when you are using compact-, large- and huge-memory
  10039.  models. This is because in these models, malloc will draw upon the
  10040.  far heap until it is exhausted, then turn to the near heap. In this
  10041.  case, it is possible to have valid pointers but _fheapwalk will not
  10042.  acknowledge them.
  10043.  
  10044.  For this reason, you should not assume that _fheapwalk will provide
  10045.  information about all your pointers, or you should use both _fheapwalk
  10046.  and _nheapwalk to check both the near heap and the far heap.
  10047.  
  10048.  
  10049.  229. C 5.10 Doesn't Implement Multibyte Integer Character Constants
  10050.  
  10051.  Product Version(s): 5.10   | 5.10
  10052.  Operating System:   MS-DOS | OS/2
  10053.  Flags: ENDUSER |
  10054.  Last Modified: 28-NOV-1988    ArticleIdent: Q38328
  10055.  
  10056.  Page 28 of the ANSI C draft proposal X3J11/88-001 describes an integer
  10057.  character constant as being a sequence of one or more multibyte
  10058.  characters enclosed in single quotation marks, e.g. 'a' or 'ab'.
  10059.  
  10060.  Page 21 of the "Microsoft C 5.1 Optimizing Compiler Language
  10061.  Reference Guide" states that an integer character constant
  10062.  is formed by enclosing a single character from the representable
  10063.  character set within single quotation marks. It makes no reference to
  10064.  multibyte character constants (e.g. 'ab'). If a source file has the
  10065.  character constant defined as follows, the error "C2015: Too many
  10066.  chars in constant" is generated:
  10067.  
  10068.     int ch = 'ab';
  10069.  
  10070.  This error is correct, because Microsoft C Version 5.10 does not
  10071.  implement multi-character integer character constants.  Note that
  10072.  page 29 of the draft standard says that such constructions are
  10073.  "implementation-defined."
  10074.  
  10075.  
  10076.  230. sscanf Example Using a Comma (,) as Delimiter
  10077.  
  10078.  Product Version(s): 5.10   | 5.10
  10079.  Operating System:   MS-DOS | OS/2
  10080.  Flags: ENDUSER | s_quickc
  10081.  Last Modified: 12-DEC-1988    ArticleIdent: Q38335
  10082.  
  10083.  The example below shows how to use the sscanf C Run-Time function
  10084.  to read from an internal buffer delimiting fields with a comma (,).
  10085.  The key is to use the brackets in the format of sscanf function. The
  10086.  format would be %[^','], which tells the function to read from the
  10087.  buffer until a comma (,) is reached.
  10088.  
  10089.  The following is a C source example illustrating the use of brackets
  10090.  and the caret (^):
  10091.  
  10092.  #include <math.h>
  10093.  #include <stdio.h>
  10094.  
  10095.  char *tokenstring = "first,25.5,second,15";
  10096.  int result, i;
  10097.  double fp;
  10098.  char o[10], f[10], s[10], t[10];
  10099.  
  10100.  main()
  10101.  {
  10102.   result = sscanf(tokenstring, "%[^','],%[^','],%[^','],%s", o, s, t, f);
  10103.   fp = atof(s);
  10104.   i  = atoi(f);
  10105.   printf("%s\n %lf\n %s\n %d\n", o, fp, t, i);
  10106.  }
  10107.  
  10108.  
  10109.  231. Shared and Instance Segments in a DLL
  10110.  
  10111.  Product Version(s): 5.10
  10112.  Operating System:   OS/2
  10113.  Flags: ENDUSER | SR# G881019-4906 -ND SINGLE S_LINK
  10114.  Last Modified: 24-JAN-1990    ArticleIdent: Q38714
  10115.  
  10116.  Question:
  10117.  
  10118.  How can I get both shared and instance data in a DLL? I'd like to have
  10119.  the default data segment (DGROUP) and most of the far segments to be
  10120.  instance data and a single far data segment to be shared data. I've
  10121.  tried to do this by doing the following:
  10122.  
  10123.  1. Isolating the data for the far segment in fardata.c and compiling
  10124.     it with -NDSEG1
  10125.  
  10126.  2. Linking with a .DEF file that contains the following:
  10127.  
  10128.      DATA    MULTIPLE NONSHARED
  10129.          SEGMENTS
  10130.                  SEG1 CLASS 'FAR_DATA' SHARED
  10131.  
  10132.  When I do this, ALL data segments (including SEG1) are instance; I
  10133.  determined this from both my test program and the output of the exehdr
  10134.  utility.
  10135.  
  10136.  How can I make the SEG1 segment shared?
  10137.  
  10138.  Response:
  10139.  
  10140.  Every time you use /NDSEG1 option compiler will generate the
  10141.  following segment definitions:
  10142.  
  10143.          SEG1        class   'FAR_DATA'
  10144.          SEG1_CONST  class   'FAR_DATA'
  10145.          SEG1_BSS    class   'FAR_DATA'
  10146.          GROUP SEG1_GROUP SEG1, SEG1_CONST, SEG1_BSS
  10147.  
  10148.  SEG1, SEG1_CONST, and SEG1_BSS are all members of the same group
  10149.  (physical segment). (SEG1_CONST AND SEG1_BSS are created automatically
  10150.  by the compiler, as is the group SEG1_GROUP.) The linker overrides the
  10151.  SEGMENTS specification if ANY of the segments in the group are left at
  10152.  the default. The solution is to ask the linker to share ALL of the
  10153.  segments in the group. In your case, insert the following into the
  10154.  .DEF file:
  10155.  
  10156.  DATA MULTIPLE NONSHARED
  10157.  SEGMENTS
  10158.          SEG1         CLASS 'FAR_DATA' SHARED
  10159.          SEG1_CONST   CLASS 'FAR_DATA' SHARED
  10160.          SEG1_BSS     CLASS 'FAR_DATA' SHARED
  10161.  
  10162.  Note: if the segment(s) you want to share are part of a group, you
  10163.  must set ALL of the segments in the group to be shared or NONE will
  10164.  be.
  10165.  
  10166.  
  10167.  232. Finding Out what Video Adapters Are Installed and Active
  10168.  
  10169.  Product Version(s): 5.10
  10170.  Operating System:   MS-DOS
  10171.  Flags: ENDUSER | video display monitor color monochrome black white b/w mono
  10172.  Last Modified: 14-DEC-1988    ArticleIdent: Q38726
  10173.  
  10174.  Question:
  10175.  
  10176.  I am writing a program that has to determine what adapter boards are
  10177.  installed in a machine. In addition, it must also determine which
  10178.  board is active. How can I use the functions supplied with C to get
  10179.  this information?
  10180.  
  10181.  Response:
  10182.  
  10183.  There is no way using the functions we supply to find out what type of
  10184.  video adapters are installed in your system. There is, however, a
  10185.  book entitled "Programmer's Guide to PC & PS/2 Video Systems,"
  10186.  published by Microsoft Press, which has an appendix that has a MASM
  10187.  example of finding out what adapters are installed. (This example
  10188.  could be translated into C.)
  10189.  
  10190.  However, even if you write code to find out what adapters are
  10191.  installed, there is no simple way to tell the graphics library to
  10192.  use an adapter other than the one it wants to use. The library will
  10193.  pick an adapter according to the following rules:
  10194.  
  10195.  1. If there is a VGA in the system, it uses it regardless of what
  10196.     other adapters are installed and regardless of what adapter is
  10197.     currently the default adapter. The only way to change this is to
  10198.     hook the BIOS INT 10h interrupt as described below.
  10199.  
  10200.  2. If there is no VGA, it uses the current adapter. This can be set
  10201.     with the MODE command in DOS before you start your program.
  10202.  
  10203.  If you hook INT 10h, you can change the behavior with the VGA to pick
  10204.  the current adapter. The _setvideomode function makes a call to INT
  10205.  10h function 1Bh to determine whether a VGA is installed or not. You
  10206.  can write code to change the return value if the VGA is not the
  10207.  current adapter, leaving it alone if the VGA is the current adapter.
  10208.  
  10209.  The _getvideoconfig function only gives information on the current
  10210.  video mode, as set by _setvideomode. It is not helpful for finding out
  10211.  what adapters are installed in your system.
  10212.  
  10213.  You can find out what adapter the library would use by making calls to
  10214.  _setvideomode. If the mode cannot be selected, _setvideomode will
  10215.  return zero. For example, if you tried to select a VGA mode and
  10216.  _setvideomode returned zero, you would know that no VGA was present in
  10217.  the system. You then could attempt to select an EGA, etc.
  10218.  
  10219.  
  10220.  233. Initializing Large Character Arrays
  10221.  
  10222.  Product Version(s): 5.10
  10223.  Operating System:   MS-DOS
  10224.  Flags: ENDUSER | SR# G881128-6987
  10225.  Last Modified: 16-JAN-1989    ArticleIdent: Q38728
  10226.  
  10227.  Question:
  10228.  
  10229.  How can I initialize an array of characters larger than 512 bytes?
  10230.  When I try initializing using a character string literal, as follows,
  10231.  
  10232.      char a[] = " *** 1000 characters *** ";
  10233.  
  10234.  I get the following compiler message:
  10235.  
  10236.      Warning C4009: string too big, trailing chars truncated
  10237.  
  10238.  Response:
  10239.  
  10240.  One method of initializing character arrays is to use a character
  10241.  string literal. The minimum limit allowed by ANSI for a characters
  10242.  string literal after concatenation is 509 characters. The limit in
  10243.  Microsoft C is 512 characters. Because the limit on the length of a
  10244.  string literal is 512 characters, you cannot initialize character
  10245.  arrays longer than 512 bytes with this method.
  10246.  
  10247.  The following won't work correctly either because the compiler treats
  10248.  these as a single string literal rather than specially as an
  10249.  initializer:
  10250.  
  10251.  char stuff[] =
  10252.          "xxx...xxx"
  10253.              ...
  10254.          "xxx...xxx";
  10255.  
  10256.  (The ANSI standard says that strings separated only by white space are
  10257.  automatically concatenated.)
  10258.  
  10259.  There are, however, a few other methods you can use that will work
  10260.  successfully, such as the following:
  10261.  
  10262.  char stuff [] =
  10263.          { 'a', ...
  10264.                 ...
  10265.            ... 'z' };
  10266.  
  10267.  However, such an initializer is no fun to type. If you decide to use
  10268.  this method, you might want to write a program that will read a data
  10269.  file and output the proper initializer.
  10270.  
  10271.  You might also want to try the following:
  10272.  
  10273.  char stuff[][10] =  {
  10274.          "0123456789",
  10275.                  ...
  10276.          "0123456789"  };
  10277.  
  10278.  The value 10 is not important EXCEPT that it must match the actual
  10279.  length of the string constants. If any of the constants are shorter
  10280.  than the length you specify, the end of that row will be padded out
  10281.  with zero bytes. If any are longer, the extra characters will be
  10282.  thrown away. You can use another pointer to access the following in
  10283.  almost any method you want:
  10284.  
  10285.     char *stuffptr = (char *) stuff;
  10286.  
  10287.  This method seems to be the most convenient.
  10288.  
  10289.  You can also define the array in MASM and link it to your C
  10290.  program. In MASM, once you've done the correct segment and public
  10291.  definitions, you could write the following:
  10292.  
  10293.  stuff   db      "abcdefghijkl"
  10294.          db      "morestuff"
  10295.          ...
  10296.          db      "laststuff"
  10297.  
  10298.  In C, you could access the array with the following:
  10299.  
  10300.  extern char stuff[];   /*    char * stuff;   will NOT work    */
  10301.  
  10302.  Finally, you could read the values into the array at run-time from a
  10303.  data file. If you read the file in large blocks, (e.g. using read or
  10304.  fread) you'll find that the I/O is quite fast.
  10305.  
  10306.  
  10307.  234. Mixing Old Declarations with Prototypes Causes Passing Errors
  10308.  
  10309.  Product Version(s): 5.10
  10310.  Operating System:   MS-DOS
  10311.  Flags: ENDUSER | SR# G881107-5854
  10312.  Last Modified: 12-DEC-1988    ArticleIdent: Q38729
  10313.  
  10314.  Question:
  10315.  
  10316.  It is my understanding that both of the following functions should
  10317.  produce identical results:
  10318.  
  10319.  float AAA(float x1, float x2)
  10320.  {
  10321.      x1 = x2;
  10322.  }
  10323.  
  10324.  float BBB(x1,x2)
  10325.  float x1,x2;
  10326.  {
  10327.      x1 = x2;
  10328.  }
  10329.  
  10330.  However, they don't. Looking at the code, I see that in BBB, the two
  10331.  parameters are treated as double instead of float. When I compile with
  10332.  the /Zg switch, which generates function prototypes, the following
  10333.  prototypes are generated:
  10334.  
  10335.  extern  float AAA(float x1, float x2);
  10336.  extern  float BBB(double x1, double x2);
  10337.  
  10338.  Why is this behavior occuring?
  10339.  
  10340.  Response:
  10341.  
  10342.  The following is from the May 5, 1988 ANSI draft, Section 3.3.2.2:
  10343.  
  10344.  "If the expression that denotes the called function has a type that
  10345.  does not include a prototype...arguments that have type float are
  10346.  promoted to double.
  10347.  
  10348.  "If the expression that denotes the called function has a type that
  10349.  includes a prototype, the arguments are implicitly converted, as if
  10350.  by assignment, to the types of the corresponding parameters."
  10351.  
  10352.  For AAA, you're using the new function definition style. Note that if
  10353.  you call this function (perhaps in another module) without a prototype
  10354.  in scope, you'll have problems because you'll pass doubles rather than
  10355.  floats (see first paragraph above).
  10356.  
  10357.  BBB uses the old style of definition as described in K & R. Because
  10358.  K & R specified that the floats are to be widened to doubles when
  10359.  they're passed to functions (and in a variety of other situations
  10360.  as well), the old style declarations maintain the old semantics.
  10361.  
  10362.  Therefore, the /Zg switch is correctly generating the function
  10363.  prototypes.
  10364.  
  10365.  Your program wouldn't run when you declared the following prototype
  10366.  before calling BBB because the prototype that was in scope when you
  10367.  CALLED BBB did not match the implicit prototype generated when the
  10368.  function was defined:
  10369.  
  10370.     void BBB(float, float);
  10371.  
  10372.  As a result, you passed floats to a function that was expecting
  10373.  doubles.
  10374.  
  10375.  
  10376.  235. Changing Default int to 32 Bits
  10377.  
  10378.  Product Version(s): 4.00 5.00 5.10 | 5.10
  10379.  Operating System:   MS-DOS         | OS/2
  10380.  Flags: END-USER | SR# G881110-6126
  10381.  Last Modified: 12-DEC-1988    ArticleIdent: Q38730
  10382.  
  10383.  Question:
  10384.  
  10385.  I am porting a VERY large C program from another C compiler to OS/2.
  10386.  In the other compiler, the type int is defined as being the same as
  10387.  long (i.e., 32 bits). In Microsoft C, int is defined as being the same
  10388.  as short (i.e., 16 bits).
  10389.  
  10390.  Is there a compiler switch to change int to long rather than short?
  10391.  
  10392.  Response:
  10393.  
  10394.  There's no compiler switch that changes the default int to long rather
  10395.  than short. If you included a "typedef long int;" or a "#define int
  10396.  long" in each and every module you compiled, you would take care of
  10397.  some of the problems. However, redefining the identifier "int" is
  10398.  likely to cause you severe and difficult-to-find problems. We
  10399.  emphatically do NOT recommend it.
  10400.  
  10401.  Note: K & R and ANSI are both very clear that int could be any size,
  10402.  provided that it's at least 16 bits. It is bad coding practice to rely
  10403.  on 32-bit ints because it makes porting code difficult.
  10404.  
  10405.  Changing all int variables to long causes your program to run very
  10406.  slowly because whenever it does arithmetic, it will have to do slower
  10407.  32-bit arithmetic rather than the more efficient built-in 16-bit
  10408.  arithmetic. This situation is true even on 80386 processors because
  10409.  current versions of our compilers do not support the generation of
  10410.  code that takes advantage of the 80386's 32-bit registers.
  10411.  
  10412.  A far better strategy is to change only the variables that need to be
  10413.  long to long. This way, you will avoid a lot of unintended side
  10414.  effects and you will not do more 32-bit arithmetic than is necessary.
  10415.  
  10416.  
  10417.  236. Overflow in Integer Math Expressions Not Checked
  10418.  
  10419.  Product Version(s): 4.00 5.00 5.10  | 5.10
  10420.  Operating System:   MS-DOS          | OS/2
  10421.  Flags: ENDUSER | S_QUICKC
  10422.  Last Modified: 12-DEC-1988    ArticleIdent: Q38733
  10423.  
  10424.  The operations performed by the integer arithmetic and shift operators
  10425.  do not check for overflow or underflow conditions. Information may be
  10426.  lost if the result of an operation cannot be represented in the type of
  10427.  the operands after conversion. All expressions are evaluated prior to
  10428.  assignment to a variable.
  10429.  
  10430.  Rules for numeric conversion are described on Page 115 of the
  10431.  "Microsoft C Language Reference" manual.
  10432.  
  10433.  The following example demonstrates the overflow condition:
  10434.  
  10435.  #include <stdio.h>
  10436.  void main(void);
  10437.  void main()
  10438.  {
  10439.  long l;
  10440.  
  10441.      l = 70 * 1000;              /* First Example            */
  10442.      printf( "l = %ld\n", l );   /* l = 4464 = 70000 % 65536 */
  10443.                                  /* Overflow not caught!!!   */
  10444.  
  10445.      l = 70L * 1000;             /* Second Example           */
  10446.      printf( "l = %ld\n", l );   /* l = 70000                */
  10447.                                  /* arithmetic in long--no   */
  10448.                                  /*   overflow               */
  10449.  }
  10450.  
  10451.  In the first example, 70 and 1000 are considered as integers. Because
  10452.  both are integer types, integer math is being performed. Integers can
  10453.  have at most a value of 32,767. When 70 is multiplied to 1000, the
  10454.  product exceeds the maximum value that an integer can hold. Overflow
  10455.  is not checked and information is lost. Thus we get a value of 4464,
  10456.  which is 70,000 mod 65,536.
  10457.  
  10458.  The workaround is the second example. Conversions occur if the types
  10459.  of the operands are different. Because 70 is a long integer (32 bits.
  10460.  Without the L, it is considered a normal integer of 16 bits). Because
  10461.  a long integer is used, all operands will be converted to long and the
  10462.  math will be done using 32-bit arithmetic. The product is large enough
  10463.  to handle the multiplication, so the correct result of 70,000 is
  10464.  generated.
  10465.  
  10466.  
  10467.  237. Viewing Array Elements in CodeView
  10468.  
  10469.  Product Version(s): 5.00 5.10 | 5.10
  10470.  Operating System:   MS-DOS    | OS/2
  10471.  Flags: ENDUSER |
  10472.  Last Modified: 12-DEC-1988    ArticleIdent: Q38735
  10473.  
  10474.  Question:
  10475.  
  10476.  In CodeView, why am I unable to view elements of an array with an
  10477.  index of type char in my C program? Whenever I do so, I get the
  10478.  following error:
  10479.  
  10480.     "operand types incorrect for this operation"
  10481.  
  10482.  Response:
  10483.  
  10484.  Using a char variable to index an array is only valid in the C
  10485.  language. As CodeView supports multiple languages, it does not allow
  10486.  a char variable to index into an array, even if the program is written
  10487.  in C.
  10488.  
  10489.  For a workaround to view elements of an array indexed by a variable of
  10490.  type "char", you need to cast the variable to an int type in
  10491.  CodeView's Dialog Box as follows:
  10492.  
  10493.     > ? buffer[(int)i]
  10494.  
  10495.  The following code sample demonstrates the situation:
  10496.  
  10497.  #include <stdio.h>
  10498.  main()
  10499.  {
  10500.     int  j = 5;
  10501.     char i = 5;
  10502.     char buffer[10];
  10503.  
  10504.     scanf("%s",buffer);
  10505.  
  10506.  }
  10507.  
  10508.  When the above program is loaded, CodeView allows you to view
  10509.  the fifth element of the array with the following commands:
  10510.  
  10511.     > ?buffer[5]
  10512.  
  10513.     > ?buffer[j].
  10514.  
  10515.  However, the following command causes the error: "operand types
  10516.  incorrect for this operation":
  10517.  
  10518.     > ?buffer[i]
  10519.  
  10520.  
  10521.  238. Error L1006 Option : Stack Size Exceeds 65535 Bytes
  10522.  
  10523.  Product Version(s): 5.00 5.10 | 5.10
  10524.  Operating System:   MS-DOS    | OS/2
  10525.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error docerr
  10526.  Last Modified:  7-DEC-1988    ArticleIdent: Q38769
  10527.  
  10528.  The following error is from "Linker Error Messages" in (1) the manual
  10529.  "CodeView and Utilities," Section C.2, Page 360, and in (2) the
  10530.  "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 365:
  10531.  
  10532.  (1)
  10533.  L1010       option : stack size exceeds 65536 bytes
  10534.  
  10535.              The size specified for the stack in the /STACK option of
  10536.              the LINK command was more than 65,536 bytes.
  10537.  
  10538.  (2)
  10539.  L1006       option : stack size exceeds 65535 bytes
  10540.  
  10541.              The size specified for the stack was more than 65,535
  10542.              bytes.
  10543.  
  10544.  Fatal errors cause the linker to stop execution. Fatal error messages
  10545.  have the following format:
  10546.  
  10547.     location : fatal error L1xxx: messagetext
  10548.  
  10549.  In these messages, location is the input file associated with the
  10550.  error, or LINK if there is no input file. If the input file is an OBJ
  10551.  or LIB file and has a module name, the module name is enclosed in
  10552.  parentheses.
  10553.  
  10554.  The documentation of the error in the "CodeView and Utilities" manual
  10555.  is incorrect. The error number should be L1006, not L1010. The upper
  10556.  limit of the stack as given in both the error message and its
  10557.  description should be 65535, not 65536. The QuickC manual is correct.
  10558.  
  10559.  This error is documented in the files ERRMSG.DOC for Microsoft C
  10560.  Version 5.10, README.DOC for Microsoft Macro Assembler Version 5.10,
  10561.  CVREADME.DOC for Microsoft FORTRAN Version 4.10, and README.DOC for
  10562.  Microsoft Pascal Version 4.00, but the description given has a
  10563.  documentation error. The error is given as:
  10564.  
  10565.    L1006   <option-text>: stack size exceeds 65535 bytes
  10566.  
  10567.    The value given as a parameter to the /STACKSIZE option exceeds
  10568.    the maximum allowed.
  10569.  
  10570.  The option /STACKSIZE is wrong. The LINK option to change the stack is
  10571.  either /STACK or /ST. Specifying /STACKSIZE will generate the error:
  10572.  
  10573.     LINK : fatal error L1002: STACKSIZE : unrecognized option name
  10574.  
  10575.  
  10576.  239. Error L1081 Out of Space for Run File
  10577.  
  10578.  Product Version(s): 5.00 5.10 | 5.10
  10579.  Operating System:   MS-DOS    | OS/2
  10580.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10581.  Last Modified:  7-DEC-1988    ArticleIdent: Q38790
  10582.  
  10583.  The following error is from "Linker Error Messages" in the manual
  10584.  "CodeView and Utilities," Section C.2, Page 364, and in the "Microsoft
  10585.  QuickC Compiler Programmer's Guide," Section D.4, Page 369:
  10586.  
  10587.  L1081       out of space for run file
  10588.  
  10589.              The disk on which the .EXE file was being written was
  10590.              full.
  10591.  
  10592.              Free more space on the disk and restart the linker.
  10593.  
  10594.  Fatal errors cause the linker to stop execution. Fatal error messages
  10595.  have the following format:
  10596.  
  10597.     location : fatal error L1xxx: messagetext
  10598.  
  10599.  In these messages, location is the input file associated with the
  10600.  error, or LINK if there is no input file. If the input file is an OBJ
  10601.  or LIB file and has a module name, the module name is enclosed in
  10602.  parentheses.
  10603.  
  10604.  
  10605.  240. Error L1087 Unexpected End-of-File on Scratch File
  10606.  
  10607.  Product Version(s): 5.00 5.10 | 5.10
  10608.  Operating System:   MS-DOS    | OS/2
  10609.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10610.  Last Modified:  7-DEC-1988    ArticleIdent: Q38795
  10611.  
  10612.  The following error is from "Linker Error Messages" in the manual
  10613.  "CodeView and Utilities," Section C.2, Page 364, and in the "Microsoft
  10614.  QuickC Compiler Programmer's Guide," Section D.4, Page 370:
  10615.  
  10616.  L1087       unexpected end-of-file on scratch file
  10617.  
  10618.              The disk with the temporary linker-output file was
  10619.              removed.
  10620.  
  10621.  Fatal errors cause the linker to stop execution. Fatal error messages
  10622.  have the following format:
  10623.  
  10624.     location : fatal error L1xxx: messagetext
  10625.  
  10626.  In these messages, location is the input file associated with the
  10627.  error, or LINK if there is no input file. If the input file is an OBJ
  10628.  or LIB file and has a module name, the module name is enclosed in
  10629.  parentheses.
  10630.  
  10631.  This error can be caused by insufficient space on the disk (hard,
  10632.  floppy, or RAM) where the temporary file is being written.
  10633.  
  10634.  
  10635.  241. Error L2002 Fixup Overflow Near Number...
  10636.  
  10637.  Product Version(s): 5.00 5.10 | 5.10
  10638.  Operating System:   MS-DOS    | OS/2
  10639.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10640.  Last Modified:  7-DEC-1988    ArticleIdent: Q38806
  10641.  
  10642.  The L2002 error below is from "Linker Error Messages" in the manual
  10643.  "CodeView and Utilities," Section C.2, Page 366, and in the "Microsoft
  10644.  QuickC Compiler Programmer's Guide," Section D.4, Page 372.
  10645.  
  10646.  The following is the error:
  10647.  
  10648.  L2002       fixup overflow near number in frame seg segname target seg
  10649.              segname target offset number
  10650.  
  10651.              The following conditions can cause this error:
  10652.  
  10653.              A small-model program is compiled with the /NT option.
  10654.  
  10655.              A group is larger than 64K.
  10656.  
  10657.              The program contains an intersegment short jump or
  10658.              intersegment short call.
  10659.  
  10660.              The name of a data item in the program conflicts with
  10661.              that of a subroutine in a library included in the
  10662.              link.
  10663.  
  10664.              An EXTRN declaration in an assembly-language source
  10665.              file appeared inside the body of a segment, as in the
  10666.              following example:
  10667.  
  10668.                  code   SEGMENT public 'CODE'
  10669.                         EXTRN   main:far
  10670.                  start  PROC    far
  10671.                         call    main
  10672.                         ret
  10673.                  start  ENDP
  10674.                  code   ENDS
  10675.  
  10676.                  The following construction is preferred:
  10677.  
  10678.                         EXTRN   main:far
  10679.                  code   SEGMENT public 'CODE'
  10680.                  start  PROC    far
  10681.                         call    main
  10682.                         ret
  10683.                  start  ENDP
  10684.                  code   ENDS
  10685.  
  10686.              Revise the source file and recreate the object file. (For
  10687.              information about frame and target segments, refer to the
  10688.              "Microsoft MS-DOS Programmer's Reference.")
  10689.  
  10690.  Nonfatal errors indicate problems in the executable file. LINK
  10691.  produces the executable file. Nonfatal error messages have the
  10692.  following format:
  10693.  
  10694.     location : error L2xxx: messagetext
  10695.  
  10696.  In these messages, location is the input file associated with the
  10697.  error, or LINK if there is no input file. If the input file is an OBJ
  10698.  or LIB file and has a module name, the module name is enclosed in
  10699.  parentheses.
  10700.  
  10701.  Force data outside of DGROUP by using the /Gt compiler switch along
  10702.  with a large data model (compact, large, or huge).
  10703.  
  10704.  Using the linker switch /CO twice can cause this. For example, when
  10705.  LINK is invoked with /CO when a LINK environment variable is also set
  10706.  to /CO, then this situation results.
  10707.  
  10708.  
  10709.  242. Error L1070 Segment Size Exceeds 64K
  10710.  
  10711.  Product Version(s): 5.00 5.10 | 5.10
  10712.  Operating System:   MS-DOS    | OS/2
  10713.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10714.  Last Modified: 12-JAN-1989    ArticleIdent: Q38807
  10715.  
  10716.  The following error is from "Linker Error Messages" in (1) the manual
  10717.  "CodeView and Utilities," Section C.2, Page 363, and in (2) the
  10718.  "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 369:
  10719.  
  10720.  (1)
  10721.  L1070       segment size exceeds 64K
  10722.  
  10723.              A single segment contained more than 64K of code or data.
  10724.  
  10725.              Try compiling and linking using the large model.
  10726.  
  10727.  (2)
  10728.  L1070       name: segment size exceeds 64K
  10729.  
  10730.              The specified segment contained more than 64K of code or
  10731.              data.
  10732.  
  10733.              Try compiling and linking using the large model.
  10734.  
  10735.  Fatal errors cause the linker to stop execution. Fatal error messages
  10736.  have the following format:
  10737.  
  10738.     location : fatal error L1xxx: messagetext
  10739.  
  10740.  In these messages, location is the input file associated with the
  10741.  error, or LINK if there is no input file. If the input file is an OBJ
  10742.  or LIB file and has a module name, the module name is enclosed in
  10743.  parentheses.
  10744.  
  10745.  Use a large data model (compact, large, or huge). Try applying the /Gt
  10746.  compilation option to lower the threshhold.
  10747.  
  10748.  
  10749.  243. Error L1072 Common Area Longer than 65536 Bytes
  10750.  
  10751.  Product Version(s): 5.00 5.10 | 5.10
  10752.  Operating System:   MS-DOS    | OS/2
  10753.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10754.  Last Modified: 12-JAN-1989    ArticleIdent: Q38808
  10755.  
  10756.  The following error is from "Linker Error Messages" in (1) the manual
  10757.  "CodeView and Utilities," Section C.2, Page 364, and in (2) the
  10758.  "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 369:
  10759.  
  10760.  L1072       common area longer than 65536 bytes
  10761.  
  10762.  (1)         The program had more than 64K of communal variables. This
  10763.              error cannot appear with object files generated by the
  10764.              Microsoft Macro Assembler, MASM. It occurs only with
  10765.              programs produced by the Microsoft FORTRAN or C Compilers
  10766.              or other compilers that support communal variables.
  10767.  
  10768.  (2)         The program had more than 64K of communal variables. This
  10769.              error cannot appear with object files generated by the
  10770.              Microsoft Macro Assembler, MASM. It occurs only with
  10771.              programs produced by the Microsoft QuickC Compiler or
  10772.              other compilers that support communal variables.
  10773.  
  10774.  Fatal errors cause the linker to stop execution. Fatal error messages
  10775.  have the following format:
  10776.  
  10777.     location : fatal error L1xxx: messagetext
  10778.  
  10779.  In these messages, location is the input file associated with the
  10780.  error, or LINK if there is no input file. If the input file is an OBJ
  10781.  or LIB file and has a module name, the module name is enclosed in
  10782.  parentheses.
  10783.  
  10784.  Use a large data model (compact, large, or huge). Try applying the /Gt
  10785.  compilation option to lower the threshhold.
  10786.  
  10787.  
  10788.  244. Error L1085 Cannot Open Temporary File
  10789.  
  10790.  Product Version(s): 5.00 5.10 | 5.10
  10791.  Operating System:   MS-DOS    | OS/2
  10792.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10793.  Last Modified:  7-DEC-1988    ArticleIdent: Q38809
  10794.  
  10795.  The following error is from "Linker Error Messages" in the manual
  10796.  "CodeView and Utilities," Section C.2, Page 364, and in the "Microsoft
  10797.  QuickC Compiler Programmer's Guide," Section D.4, Page 370:
  10798.  
  10799.  L1085       cannnot open temporary file
  10800.  
  10801.              The disk or the root directory was full.
  10802.  
  10803.              Delete or move files to make space.
  10804.  
  10805.  Fatal errors cause the linker to stop execution. Fatal error messages
  10806.  have the following format:
  10807.  
  10808.     location : fatal error L1xxx: messagetext
  10809.  
  10810.  In these messages, location is the input file associated with the
  10811.  error, or LINK if there is no input file. If the input file is an OBJ
  10812.  or LIB file and has a module name, the module name is enclosed in
  10813.  parentheses.
  10814.  
  10815.  This error can be caused by insufficient file handles. Resident
  10816.  software (TSR) can use up some handles, or can cause other kinds of
  10817.  interference that can cause this error.
  10818.  
  10819.  
  10820.  245. Error L1089 Filename : Cannot Open Response File
  10821.  
  10822.  Product Version(s): 5.00 5.10 | 5.10
  10823.  Operating System:   MS-DOS    | OS/2
  10824.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10825.  Last Modified: 11-JAN-1990    ArticleIdent: Q38810
  10826.  
  10827.  The following error is from "Linker Error Messages" in the manual
  10828.  "CodeView and Utilities," Section C.2, Page 365, and in the "Microsoft
  10829.  QuickC Compiler Programmer's Guide," Section D.4, Page 370:
  10830.  
  10831.  L1089       filename : cannot open response file
  10832.  
  10833.              LINK could not find the specified response file.
  10834.  
  10835.              This usually indicates a typing error.
  10836.  
  10837.  Fatal errors cause the linker to stop execution. Fatal error messages
  10838.  have the following format:
  10839.  
  10840.     location : fatal error L1xxx: messagetext
  10841.  
  10842.  In these messages, location is the input file associated with the
  10843.  error, or LINK if there is no input file. If the input file is an OBJ
  10844.  or LIB file and has a module name, the module name is enclosed in
  10845.  parentheses.
  10846.  
  10847.  Also, check the TMP environment variable setting and/or TSR's.
  10848.  
  10849.  
  10850.  246. Error L2029 Unresolved Externals
  10851.  
  10852.  Product Version(s): 5.00 5.10 | 5.10
  10853.  Operating System:   MS-DOS    | OS/2
  10854.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10855.  Last Modified: 11-JAN-1990    ArticleIdent: Q38818
  10856.  
  10857.  The following error is from "Linker Error Messages" in the manual
  10858.  "CodeView and Utilities", Section C.2, Page 368, and in the "Microsoft
  10859.  QuickC Compiler Programmer's Guide," Section D.4, Page 373:
  10860.  
  10861.  L2029       unresolved externals
  10862.  
  10863.              One or more symbols were declared to be external in one or
  10864.              more modules, but they were not publicly defined in any of
  10865.              the modules or libraries. A list of the unresolved
  10866.              external references appears after the message, as shown in
  10867.              the following example:
  10868.  
  10869.              EXIT in file(s):
  10870.               MAIN.OBJ (main.for)
  10871.              OPEN in file(s):
  10872.               MAIN.OBJ (main.for)
  10873.  
  10874.              The name that comes before in file(s) is the unresolved
  10875.              external symbol. On the next line is a list of object
  10876.              modules that have made references to this symbol. This
  10877.              message and the list are also written to the map file, if
  10878.              one exists.
  10879.  
  10880.  Nonfatal errors indicate problems in the executable file. LINK
  10881.  produces the executable file. Nonfatal error messages have the
  10882.  following format:
  10883.  
  10884.     location : error L2xxx: messagetext
  10885.  
  10886.  In these messages, location is the input file associated with the
  10887.  error, or LINK if there is no input file. If the input file is an OBJ
  10888.  or LIB file and has a module name, the module name is enclosed in
  10889.  parentheses.
  10890.  
  10891.  This linker error message means that a reference to a function or
  10892.  procedure was made, but the actual routine to that reference was never
  10893.  found (in either a library or in another object module). This message
  10894.  is not in regards to inclusion or exclusion of include files in a C
  10895.  program. (Include files in a C program usually do not contain
  10896.  functions, but rather function prototypes.) If this error message
  10897.  should occur, check the following:
  10898.  
  10899.  1. Make sure the command line used to invoke the linker or the
  10900.     compiler/linker is correct.
  10901.  
  10902.  2. Check that you have specified all libraries that are needed by
  10903.     the program (e.g. graphics.lib, a third-party library).
  10904.  
  10905.  3. Check the spelling of the procedure or function name in the
  10906.     program and make sure it corresponds to how the function is
  10907.     actually declared.
  10908.  
  10909.  4. Make a listing of the libraries that are being linked with to
  10910.     see if the missing procedure or function is indeed in the library.
  10911.     This process will require the use of LIB.EXE.
  10912.  
  10913.  5. If you are in QuickC and this message occurs, check to see if
  10914.     the function that is being called is contained in the core library.
  10915.     If it isn't, you need to set a Program List in the QuickC editor.
  10916.  
  10917.  6. Check the name that the linker can't resolve. If the name is
  10918.     preceded by two underscores, then most likely it is either an
  10919.     internal routine for startup or other internal functions or the
  10920.     library was built with an incorrect version of LIB.
  10921.  
  10922.  Make sure a main() has been declared and/or a function in C wasn't
  10923.  preceded with an undesired underscore. This error can also occur if a
  10924.  C program is being mixed with an assembler routine and the assembler
  10925.  routine was not assembled with the /MX and /ML options to preserve the
  10926.  case of the functions, or the function in the assembler program didn't
  10927.  have an underscore in front of its name to make it compatible with the
  10928.  C naming convention.
  10929.  
  10930.  
  10931.  247. Error L2041 Stack Plus Data Exceeds 64K
  10932.  
  10933.  Product Version(s): 5.00 5.10 | 5.10
  10934.  Operating System:   MS-DOS    | OS/2
  10935.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10936.  Last Modified:  7-DEC-1988    ArticleIdent: Q38819
  10937.  
  10938.  The error below is from "Linker Error Messages" in the "Microsoft
  10939.  QuickC Compiler Programmer's Guide," Section D.4, Page 374. It is also
  10940.  in the file ERRMSG.DOC on Compiler Disk 1 for Microsoft C Version 5.10
  10941.  and on the Setup Disk for Microsoft C Version 5.00, and in the file
  10942.  README.DOC on Disk 1 for Microsoft Macro Assembler Version 5.10, and
  10943.  in the file CVREADME.DOC on the CodeView for MS-DOS disk for Microsoft
  10944.  FORTRAN Version 4.10. It is not found in the manual "CodeView and
  10945.  Utilities."
  10946.  
  10947.  The following is the error:
  10948.  
  10949.  L2041       stack plus data exceeds 64K
  10950.  
  10951.              The combined size of the program stack segment plus DGROUP
  10952.              was greater than 64K; as a result, the program will not
  10953.              load up correctly.
  10954.  
  10955.  Nonfatal errors indicate problems in the executable file. LINK
  10956.  produces the executable file. Nonfatal error messages have the
  10957.  following format:
  10958.  
  10959.     location : error L2xxx: messagetext
  10960.  
  10961.  In these messages, location is the input file associated with the
  10962.  error, or LINK if there is no input file. If the input file is an OBJ
  10963.  or LIB file and has a module name, the module name is enclosed in
  10964.  parentheses.
  10965.  
  10966.  To correct the problem, do the following:
  10967.  
  10968.  1. Reduce the stack size.
  10969.  
  10970.  2. Use a large data model (compact, large, or huge). Try applying the
  10971.     /Gt compilation option to lower the threshhold.
  10972.  
  10973.  3. Use the FAR keyword to move data out of DGROUP.
  10974.  
  10975.  
  10976.  248. Error L2025 Name : Symbol Defined More than Once
  10977.  
  10978.  Product Version(s): 5.00 5.10 | 5.10
  10979.  Operating System:   MS-DOS    | OS/2
  10980.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  10981.  Last Modified:  7-DEC-1988    ArticleIdent: Q38820
  10982.  
  10983.  The following error is from "Linker Error Messages" in the manual
  10984.  "CodeView and Utilities", Section C.2, Page 368, and in the "Microsoft
  10985.  QuickC Compiler Programmer's Guide," Section D.4, Page 373:
  10986.  
  10987.  L2025       name : symbol defined more than once
  10988.  
  10989.              Remove the extra symbol definition from the object file.
  10990.  
  10991.  Nonfatal errors indicate problems in the executable file. LINK
  10992.  produces the executable file. Nonfatal error messages have the
  10993.  following format:
  10994.  
  10995.     location : error L2xxx: messagetext
  10996.  
  10997.  In these messages, location is the input file associated with the
  10998.  error, or LINK if there is no input file. If the input file is an OBJ
  10999.  or LIB file and has a module name, the module name is enclosed in
  11000.  parentheses.
  11001.  
  11002.  One way this error can be caused is by incorrectly using or omitting a
  11003.  keyword such as pascal. If the included function prototype has the
  11004.  keyword and the library routine does not, or vice versa, the linker
  11005.  reports that the function is defined more than once.
  11006.  
  11007.  
  11008.  249. %TMP% in NEW_VARS.BAT Causes Fatal Error C1042
  11009.  
  11010.  Product Version(s): 5.00 5.10 | 5.10
  11011.  Operating System:   MS-DOS    | OS/2
  11012.  Flags: ENDUSER | s_pascal h_fortran
  11013.  Last Modified: 12-DEC-1988    ArticleIdent: Q38839
  11014.  
  11015.  If you append new_vars.bat to your AUTOEXEC.BAT and your TMP
  11016.  environment variable is already set for specifying the drive,
  11017.  directory compiler, and linker to which temporary files should be
  11018.  written, %TMP% causes the following error message:
  11019.  
  11020.     Fatal-Error C1042: cannot open intermediate file -- no
  11021.                        such file or directory.
  11022.  
  11023.  This message occurs because the TMP variable should specify only one
  11024.  directory.
  11025.  
  11026.  %TMP% appends any TMP directories already defined at that location.
  11027.  Generally, it is best not to have any %<environmental variable>%
  11028.  symbols in AUTOEXEC.BAT because it should be the first place the
  11029.  environment is defined.
  11030.  
  11031.  
  11032.  250. Error L1126, Error L2043
  11033.  
  11034.  Product Version(s): 5.00 5.10 | 5.10
  11035.  Operating System:   MS-DOS    | OS/2
  11036.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_link s_error
  11037.  Last Modified: 19-DEC-1988    ArticleIdent: Q38979
  11038.  
  11039.  The information below describes linker-error messages L1126 and L2043.
  11040.  
  11041.  The following error is from "Linker Error Messages" in (1) the manual
  11042.  "CodeView and Utilities", Section C.2, Page 366, and in (2) the
  11043.  "Microsoft QuickC Compiler Programmer's Guide," Section D.4, Page 374.
  11044.  It is also in (3) the file ERRMSG.DOC on Compiler Disk 1 for Microsoft
  11045.  C Version 5.10 and on the Setup Disk for Microsoft C Version 5.00,
  11046.  also in the file README.DOC on Disk 1 for Microsoft Macro Assembler
  11047.  Version 5.10, also in the file CVREADME.DOC on the CodeView for MS-DOS
  11048.  disk for Microsoft FORTRAN Version 4.10:
  11049.  
  11050.  (1)
  11051.  L1126       starting address __aulstart not found
  11052.  
  11053.              You tried to create a Quick library without linking with
  11054.              the required LIB library.
  11055.  
  11056.  (2)
  11057.  L2043       starting address __aulstart not found
  11058.  
  11059.              When you build a Quick library using the /Q option, the
  11060.              linker expects to find the symbol __aulstart defined as a
  11061.              starting address.
  11062.  
  11063.  (3)
  11064.  L2043       Quick Library support module missing
  11065.  
  11066.              When creating a Quick library, you did not link with the
  11067.              required QUICKLIB.OBJ module.
  11068.  
  11069.  Fatal errors cause the linker to stop execution. Fatal error messages
  11070.  have the following format:
  11071.  
  11072.  location : fatal error L1xxx: messagetext
  11073.  
  11074.  Nonfatal errors indicate problems in the executable file. LINK
  11075.  produces the executable file. Nonfatal error messages have the
  11076.  following format:
  11077.  
  11078.  location : error L2xxx: messagetext
  11079.  
  11080.  In these messages, location is the input file associated with the
  11081.  error, or LINK if there is no input file. If the input file is an OBJ
  11082.  or LIB file and has a module name, the module name is enclosed in
  11083.  parentheses.
  11084.  
  11085.  
  11086.  251. Error U1188 Cannot Write to VM
  11087.  
  11088.  Product Version(s): 5.00 5.10 | 5.10
  11089.  Operating System:   MS-DOS    | OS/2
  11090.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_util s_error
  11091.  Last Modified: 21-DEC-1988    ArticleIdent: Q39018
  11092.  
  11093.  The information below describes library-error message U1188.
  11094.  
  11095.  The following error is from "LIB Error Messages" in (1) the manual
  11096.  "CodeView and Utilities", Section C.3, Page 373, and in (2) the
  11097.  "Microsoft QuickC Compiler Programmer's Guide," Section D.5, Page 379:
  11098.  
  11099.  U1188       cannot write to VM
  11100.  
  11101.  (1)         Note the circumstances of the failure and notify Microsoft
  11102.              Corporation by using the Product Assistance Request form
  11103.              at the back of one of your manuals.
  11104.  
  11105.  (2)         Note the circumstances of the failure and notify Microsoft
  11106.              Corporation, using the Product Assistance Request form at
  11107.              the back of this manual.
  11108.  
  11109.  IMPORTANT NOTE:  This error can also occur when a temporary file
  11110.  cannot be created, possibly because the disk is full.
  11111.  
  11112.  Error messages generated by the Microsoft Library Manager, LIB, have
  11113.  one of the following formats:
  11114.  
  11115.  {filename | LIB} : fatal error U1xxx: messagetext
  11116.  {filename | LIB} : error U2xxx: messagetext
  11117.  {filename | LIB} : warning U4xxx: messagetext
  11118.  
  11119.  The message begins with the input-file name (filename), if one exists,
  11120.  or with the name of the utility. If possible, LIB prints a warning and
  11121.  continues operation. In some cases errors are fatal and LIB terminates
  11122.  processing.
  11123.  
  11124.  
  11125.  252. Error U2157 Filename : Cannot Access File
  11126.  
  11127.  Product Version(s): 5.00 5.10 | 5.10
  11128.  Operating System:   MS-DOS    | OS/2
  11129.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_util s_error
  11130.  Last Modified: 21-DEC-1988    ArticleIdent: Q39019
  11131.  
  11132.  The following error is from "LIB Error Messages" in the manual
  11133.  "CodeView and Utilities", Section C.3, Page 374, and in the "Microsoft
  11134.  QuickC Compiler Programmer's Guide," Section D.5, Page 380:
  11135.  
  11136.  U2157       filename : cannot access file
  11137.  
  11138.              LIB was unable to open the specified file.
  11139.  
  11140.  Error messages generated by the Microsoft Library Manager, LIB, have
  11141.  one of the following formats:
  11142.  
  11143.  {filename | LIB} : fatal error U1xxx: messagetext
  11144.  {filename | LIB} : error U2xxx: messagetext
  11145.  {filename | LIB} : warning U4xxx: messagetext
  11146.  
  11147.  The message begins with the input-file name (filename), if one exists,
  11148.  or with the name of the utility. If possible, LIB prints a warning and
  11149.  continues operation. In some cases errors are fatal and LIB terminates
  11150.  processing.
  11151.  
  11152.  A hyphen (dash, - ) in a subdirectory name in the path can cause this
  11153.  error; this error occurs because of a problem in LIB.
  11154.  
  11155.  
  11156.  253. Error U2155 Modulename : Module Not In Library; Ignored
  11157.  
  11158.  Product Version(s): 5.00 5.10 | 5.10
  11159.  Operating System:   MS-DOS    | OS/2
  11160.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_util s_error
  11161.  Last Modified: 21-DEC-1988    ArticleIdent: Q39020
  11162.  
  11163.  The following error is from "LIB Error Messages" in the manual
  11164.  "CodeView and Utilities", Section C.3, Page 374, and in the
  11165.  "Microsoft QuickC Compiler Programmer's Guide," Section D.5, Page 380:
  11166.  
  11167.  U2155       modulename : module not in library; ignored
  11168.  
  11169.              The specified module was not found in the input library.
  11170.  
  11171.  Error messages generated by the Microsoft Library Manager, LIB, have
  11172.  one of the following formats:
  11173.  
  11174.  {filename | LIB} : fatal error U1xxx: messagetext
  11175.  {filename | LIB} : error U2xxx: messagetext
  11176.  {filename | LIB} : warning U4xxx: messagetext
  11177.  
  11178.  The message begins with the input-file name (filename), if one exists,
  11179.  or with the name of the utility. If possible, LIB prints a warning and
  11180.  continues operation. In some cases errors are fatal and LIB terminates
  11181.  processing.
  11182.  
  11183.  A hyphen (dash, - ) in a subdirectory name in the path can cause this
  11184.  error; this error occurs because of a problem in LIB.
  11185.  
  11186.  
  11187.  254. Error U1005 Syntax Error: Colon Missing
  11188.  
  11189.  Product Version(s): 5.00 5.10 | 5.10
  11190.  Operating System:   MS-DOS    | OS/2
  11191.  Flags: ENDUSER | s_pascal h_fortran h_masm s_quickc s_make s_error
  11192.  Last Modified: 15-JAN-1990    ArticleIdent: Q39037
  11193.  
  11194.  The following error is from "MAKE Error Messages" in the manual
  11195.  "CodeView and Utilities", Section C.4, Page 376, and in the "Microsoft
  11196.  QuickC Compiler Programmer's Guide," Section D.6, Page 382:
  11197.  
  11198.  U1005       syntax error : colon missing
  11199.  
  11200.              A line that should be an outfile/infile line lacked a
  11201.              colon indicating the separation between outfile and
  11202.              infile. MAKE expects any line following a blank line to be
  11203.              an outfile/infile line.
  11204.  
  11205.  Note: MAKE expects a blank character or tab(s) after the colon between
  11206.  outfile and infile. If such a space is missing, this error occurs.
  11207.  
  11208.  Error messages displayed by the Microsoft Program Maintenance Utility,
  11209.  MAKE, have one of the following formats:
  11210.  
  11211.     {filename | MAKE} : fatal error U1xxx: messagetext
  11212.     {filename | MAKE} : warning U4xxx: messagetext
  11213.  
  11214.  The message begins with the input-file name (filename), if one exists,
  11215.  or with the name of the utility. If possible, MAKE prints a warning
  11216.  and continues operation. In some cases, errors are fatal and MAKE
  11217.  terminates processing.
  11218.  
  11219.  This problem can also be caused by using a NMAKE compatible make file
  11220.  with MAKE.
  11221.  
  11222.  
  11223.  255. Error R6006 Bad Format on exec
  11224.  
  11225.  Product Version(s): 5.00 5.10 | 5.10
  11226.  Operating System:   MS-DOS    | OS/2
  11227.  Flags: ENDUSER | s_quickc s_error
  11228.  Last Modified: 21-DEC-1988    ArticleIdent: Q39045
  11229.  
  11230.  The following error is from "Run-Time Library Error Messages" in the
  11231.  "Microsoft C Optimizing Compiler User's Guide," Section E.4.1, Page
  11232.  283, and in the "Microsoft QuickC Compiler Programmer's Guide,"
  11233.  Section D.3.2, Page 362:
  11234.  
  11235.  R6006       bad format on exec
  11236.  
  11237.              The file to be executed by one of the exec functions was
  11238.              not in the correct format for an executable file.
  11239.  
  11240.  These messages may be generated at run time when your program has
  11241.  serious errors. Run-time error-message numbers range from R6000 to
  11242.  R6999. A run-time error message takes the following general form:
  11243.  
  11244.     run-time error R6nnn
  11245.     - messagetext
  11246.  
  11247.  Errors R6005 through R6007 occur when a child process spawned by one
  11248.  of the exec library routines fails, and DOS could not return control
  11249.  to the parent process. This error indicates that not enough memory
  11250.  remained to load the program being spawned.
  11251.  
  11252.  
  11253.  256. Error R6007 Bad Environment on exec
  11254.  
  11255.  Product Version(s): 5.00 5.10 | 5.10
  11256.  Operating System:   MS-DOS    | OS/2
  11257.  Flags: ENDUSER | s_quickc s_error
  11258.  Last Modified: 21-DEC-1988    ArticleIdent: Q39046
  11259.  
  11260.  The information below discusses the run-time error message R6007.
  11261.  
  11262.  The following error is from "Run-Time Library Error Messages" in the
  11263.  "Microsoft C Optimizing Compiler User's Guide," Section E.4.1, Page
  11264.  283, and in the "Microsoft QuickC Compiler Programmer's Guide,"
  11265.  Section D.3.2, Page 362:
  11266.  
  11267.  R6007       bad environment on exec
  11268.  
  11269.              During a call to one of the exec functions, DOS determined
  11270.              that the child process was being given a bad environment
  11271.              block.
  11272.  
  11273.  These messages may be generated at run time when your program has
  11274.  serious errors. Run-time error-message numbers range from R6000 to
  11275.  R6999. A run-time error message takes the following general form:
  11276.  
  11277.     run-time error R6nnn
  11278.     - messagetext
  11279.  
  11280.  Errors R6005 through R6007 occur when a child process spawned by one
  11281.  of the exec library routines fails, and DOS could not return control
  11282.  to the parent process. This error indicates that not enough memory
  11283.  remained to load the program being spawned.
  11284.  
  11285.  
  11286.  257. Error R6008 Not Enough Space for Arguments
  11287.  
  11288.  Product Version(s): 5.00 5.10 | 5.10
  11289.  Operating System:   MS-DOS    | OS/2
  11290.  Flags: ENDUSER | s_quickc s_error
  11291.  Last Modified: 11-JAN-1990    ArticleIdent: Q39047
  11292.  
  11293.  The information below discusses the run-time library error message
  11294.  R6008.
  11295.  
  11296.  The following error is from "Run-Time Library Error Messages" in (1)
  11297.  the "Microsoft C Optimizing Compiler User's Guide," Section E.4.1,
  11298.  Page 283, and in (2) the "Microsoft QuickC Compiler Programmer's
  11299.  Guide," Section D.3.2, Page 363:
  11300.  
  11301.  R6008       not enough space for arguments
  11302.  
  11303.  (1)         See explanation under error R6009.
  11304.  
  11305.  (2)         (no description given)
  11306.  
  11307.  These messages may be generated at run time when your program has
  11308.  serious errors. Run-time error-message numbers range from R6000 to
  11309.  R6999. A run-time error message takes the following general form:
  11310.  
  11311.     run-time error R6nnn
  11312.     - messagetext
  11313.  
  11314.  The following is the description for R6009 in the "Microsoft C
  11315.  Optimizing Compiler User's Guide":
  11316.  
  11317.     Errors R6008 and R6009 both occur at start-up if there is
  11318.     enough memory to load the program, but not enough room for
  11319.     the argv vector, the envp vector, or both. To avoid this
  11320.     problem, rewrite the _setargv or _setenvp routines (see
  11321.     Section 5.2.2, "Suppressing Command-Line Processing," for
  11322.     more information).
  11323.  
  11324.  
  11325.  258. Error R6013 Illegal Far Pointer Use
  11326.  
  11327.  Product Version(s): 5.00 5.10 | 5.10
  11328.  Operating System:   MS-DOS    | OS/2
  11329.  Flags: ENDUSER | s_quickc s_error
  11330.  Last Modified: 21-DEC-1988    ArticleIdent: Q39050
  11331.  
  11332.  The information below explains the run-time library error message
  11333.  R6013.
  11334.  
  11335.  The error below is from "Run-Time Library Error Messages" in the
  11336.  "Microsoft QuickC Compiler Programmer's Guide," Section D.3.2, Page
  11337.  363. It is not documented in the "Microsoft C Optimizing Compiler
  11338.  User's Guide" or in ERRMSG.DOC for Versions 5.00 and 5.10.
  11339.  
  11340.  The following is the error:
  11341.  
  11342.  R6013       Invalid far pointer reference
  11343.  
  11344.              An out-of-range far pointer was used in the program.
  11345.  
  11346.              This error occurs only if pointer checking is in effect
  11347.              (that is, if the program was compiled with the Pointer
  11348.              Check option in the Compile dialog box, the /Zr option on
  11349.              the QCL command line, or the pointer_check pragma in
  11350.              effect).
  11351.  
  11352.  These messages may be generated at run time when your program has
  11353.  serious errors. Run-time error-message numbers range from R6000 to
  11354.  R6999. A run-time error message takes the following general form:
  11355.  
  11356.     run-time error R6nnn
  11357.     - messagetext
  11358.  
  11359.  According to the README.DOC found on the Product Disk for Microsoft
  11360.  QuickC Version 1.00 and on the Setup Disk for QuickC Version 1.01, the
  11361.  run-time error message R6013 has changed as follows:
  11362.  
  11363.     R6013 illegal far pointer use
  11364.  
  11365.  
  11366.  259. C1004: Unexpected EOF
  11367.  
  11368.  Product Version(s): 4.00  5.00  5.10 | 5.10
  11369.  Operating System:   MS-DOS           | OS/2
  11370.  Flags: ENDUSER | s_quickc
  11371.  Last Modified: 12-DEC-1988    ArticleIdent: Q39088
  11372.  
  11373.  The fatal-compiler error "C1004: Unexpected EOF" can be caused by
  11374.  failing to end a line with a <CR>.  On pure C language statements the
  11375.  compiler ignores white space, but on statements with directives a <CR>
  11376.  is needed.
  11377.  
  11378.  This will occur if the following include file is used in a program:
  11379.  
  11380.      #include <stdio.h><CR>
  11381.      #define YES 1<CR>
  11382.      #define NO  0
  11383.  
  11384.  Without the <CR> after the third line, error C1004 will be produced by
  11385.  the compiler.
  11386.  
  11387.  
  11388.  260. Using _gettextposition and printf.
  11389.  
  11390.  Product Version(s): 5.10   | 5.10
  11391.  Operating System:   MS-DOS | OS/2
  11392.  Flags: ENDUSER | s_quickc
  11393.  Last Modified: 12-DEC-1988    ArticleIdent: Q39089
  11394.  
  11395.  When the C graphic routines are being used in a program, they should
  11396.  be used for all output to the screen, including text output. Other C
  11397.  run-time functions for output should not be used.
  11398.  
  11399.  If a C program uses the run-time function _gettextposition, the
  11400.  function _outtext should be used to output text to the screen. Using
  11401.  the function printf will cause overwritting of text or blank lines to
  11402.  be inserted on the video screen.
  11403.  
  11404.  The following program will result in unpredictable output:
  11405.  
  11406.  #include <stdio.h>
  11407.  #include <stdlib.h>
  11408.  #include <graph.h>
  11409.  
  11410.  main()
  11411.  {
  11412.     struct rccoord rcoord;
  11413.     system("cls");
  11414.     printf("11\n");
  11415.     printf("22222222\n");
  11416.     printf("333333\n");
  11417.     printf("fourth line\n");
  11418.     printf("fifth line\n");
  11419.  
  11420.     rcoord=_gettextposition();
  11421.  
  11422.     printf("6666\n");
  11423.     printf("77777777\n");
  11424.  }
  11425.  
  11426.  The work around is use _outtext instead of printf.
  11427.  
  11428.  
  11429.  261. Pattern Format for _setfillmask
  11430.  
  11431.  Product Version(s): 5.00 5.10
  11432.  Operating System:   MS-DOS
  11433.  Flags: ENDUSER | _getfillmask
  11434.  Last Modified: 29-DEC-1988    ArticleIdent: Q39215
  11435.  
  11436.  The _setfillmask function sets a background pattern using repeated
  11437.  8-by-8 pixel patterns. The mask consists of an 8-byte character array.
  11438.  
  11439.  The following example illustrates a pixel pattern:
  11440.  
  11441.                           Powers of 2
  11442.  
  11443.      decimal:   128  64  32  16  08  04  02  01
  11444.          hex:    80  40  20  10  08  04  02  01
  11445.                 --------------------------------
  11446.         byte 1 |      1   1           1   1        =   0x66
  11447.         byte 2 |      1   1           1   1        =   0x66
  11448.         byte 3 |                                   =   0x00
  11449.         byte 4 |                  1                =   0x08
  11450.         byte 5 |              1   1                =   0x18
  11451.         byte 6 |  1                           1    =   0x81
  11452.         byte 7 |      1                   1        =   0x42
  11453.         byte 8 |          1   1   1   1            =   0x3C
  11454.  
  11455.  The character array for this particular fill mask would be declared in
  11456.  a C program as follows:
  11457.  
  11458.     unsigned char *maskarray = "\x66\x66\x00\x08\x18\x81\x42\x3C";
  11459.  
  11460.  When the fill mask above is used with _setfillmask and a graphics
  11461.  function such as _rectangle or _ellipse, the pattern will create
  11462.  a continuous field of faces.
  11463.  
  11464.  
  11465.  262. Opening Files Using Command Line Arguments.
  11466.  
  11467.  Product Version(s): 5.10   | 5.10
  11468.  Operating System:   MS-DOS | OS/2
  11469.  Flags: ENDUSER | s_quickc
  11470.  Last Modified: 29-DEC-1988    ArticleIdent: Q39216
  11471.  
  11472.  File names may be specified as command line arguments to a C
  11473.  program.  The example below uses the first command line argument as
  11474.  the name of the input file and the second as the name of the output
  11475.  file.  The parameter argv, which is declared by main(), is used to
  11476.  access the command line arguments.
  11477.  
  11478.  In the example below, the following occurs:
  11479.  
  11480.  1. argv[0] will contain a full path to the source (exe) file
  11481.  
  11482.  2. argv[1] will contain the first argument, which is the input file
  11483.  name
  11484.  
  11485.  3. argv[2] will contain the second argument, which is the output file
  11486.  name
  11487.  
  11488.  The following program opens a file for reading and writing and
  11489.  also prints argv[0], argv[1], and argv[2].  Note that argc is checked
  11490.  to make sure that two argument strings were actually passed and that
  11491.  the file pointers are checked to make sure that the files were
  11492.  actually opened.
  11493.  
  11494.  #include <stdio.h>
  11495.  
  11496.  main (argc,argv)
  11497.  int argc;
  11498.  char *argv[];
  11499.  {
  11500.    FILE *in, *out;
  11501.  
  11502.    if (argc < 3)  {         /* enough arguments? */
  11503.      puts("Usage:  demo infile outfile");
  11504.      exit(1);
  11505.    }
  11506.  
  11507.    printf("%s\n", argv[0]);
  11508.    printf("%s\n", argv[1]);
  11509.    printf("%s\n", argv[2]);
  11510.  
  11511.    in  = fopen (argv[1],"r");
  11512.    out = fopen (argv[2],"w");
  11513.  
  11514.    if (in == NULL || out == NULL)  {
  11515.      puts("Could not open both files");
  11516.      exit(2);
  11517.    }
  11518.    puts("Opened both files OK");
  11519.    exit(0);
  11520.  }
  11521.  
  11522.  The command line: "C:\>demo infile outfile" produces the
  11523.  following output if infile and outfile can be opened:
  11524.  
  11525.     C:\demo.exe
  11526.     infile
  11527.     outfile
  11528.     Opened both files OK
  11529.  
  11530.  
  11531.  263. Example of C Calling a MASM Procedure
  11532.  
  11533.  Product Version(s): 5.10   | 5.10
  11534.  Operating System:   MS-DOS | OS/2
  11535.  Flags: ENDUSER | h_masm
  11536.  Last Modified: 29-DEC-1988    ArticleIdent: Q39309
  11537.  
  11538.  The sample code below demonstrates a C program calling a MASM
  11539.  procedure. The C code declares an integer and passes the integer to
  11540.  the MASM procedure called mixed(). The mixed() function has an integer
  11541.  return value. The C code is compiled in the large-memory model and the
  11542.  MASM code is assembled with the /ML option.
  11543.  
  11544.  The following is the code:
  11545.  
  11546.  #include <stdio.h>
  11547.  
  11548.  int retval, value, foo;
  11549.  extern int mixed(int);
  11550.  
  11551.  main() {
  11552.      value = 35;
  11553.      foo = 25;
  11554.      retval = 0;
  11555.      retval = mixed(foo);
  11556.      printf("%d\n%d\n",retval,value);
  11557.      }
  11558.  
  11559.        DOSSEG
  11560.        .MODEL LARGE C
  11561.        .STACK  100h
  11562.        .DATA
  11563.          Dw 0
  11564.        .FARDATA
  11565.          EXTRN _value:WORD
  11566.        .CODE
  11567.          PUBLIC _mixed
  11568.  _mixed PROC
  11569.           push  bp
  11570.           mov   bp,sp
  11571.  ; access and change _value
  11572.           mov   ax, seg _DATA
  11573.           mov   ds,ax
  11574.           mov   ax,SEG _value
  11575.           mov   es,ax
  11576.           mov   es:_value,10h
  11577.  ; return the passed variable
  11578.           mov   ax,[bp+6]
  11579.           pop   bp
  11580.           ret
  11581.  _mixed   ENDP
  11582.           END
  11583.  
  11584.  
  11585.  264. Selective Initialization of Array Elements Not Allowed
  11586.  
  11587.  Product Version(s): 5.10   | 5.10
  11588.  Operating System:   MS-DOS | OS/2
  11589.  Flags: ENDUSER |
  11590.  Last Modified: 29-DEC-1988    ArticleIdent: Q39310
  11591.  
  11592.  The ANSI C standard does not allow selective initialization of
  11593.  array elements with the following syntax:
  11594.  
  11595.     char MyArray[10] = {'a','b',,'d',,'f','g',,'i','j'};
  11596.  
  11597.  This attempt at selective initialization is illegal and will generate
  11598.  a "Syntax Error" at compile time. The following two declarations will
  11599.  compile and are valid declarations for Microsoft C Version 5.10:
  11600.  
  11601.  1. The initialization of all the elements of the array is as follows:
  11602.  
  11603.     char MyArray[10] = {'a','b','c','d','e','f','g','h','i','j'}
  11604.  
  11605.  2. The initialization of the front characters in the array is as
  11606.     follows:
  11607.  
  11608.     char MyArray[10] = {'a','b','c','d','e'}
  11609.  
  11610.  
  11611.  265. Use 0x80 to Access Drive C when Calling _bios_disk
  11612.  
  11613.  Product Version(s): 5.00 5.10
  11614.  Operating System:   MS-DOS
  11615.  Flags: ENDUSER | S_QUICKC
  11616.  Last Modified: 29-DEC-1988    ArticleIdent: Q39311
  11617.  
  11618.  Question:
  11619.  
  11620.  I am using the _bios_disk function to access my fixed disk. I have
  11621.  initialized the drive parameter to 2 to specify my fixed-disk drive.
  11622.  This function does not seem to be accessing my fixed disk. What am I
  11623.  doing wrong?
  11624.  
  11625.  Response:
  11626.  
  11627.  The first floppy drive in a computer is identified as drive 0 with
  11628.  additional floppy drives numbered sequentially. However, the first
  11629.  fixed disk is identified as drive 0x80 (128 decimal) with additional
  11630.  partitions numbered sequentially. Therefore, call _bios_disk with the
  11631.  drive parameter set to 0x80 to access the first fixed disk.
  11632.  
  11633.  The following is an example:
  11634.  
  11635.     Logical Drive    diskinfo.drive
  11636.           A                 0
  11637.           B                 1
  11638.           C                0x80
  11639.           D                0x81
  11640.           E                0x82
  11641.           .                 .
  11642.           .                 .
  11643.           .                 .
  11644.  
  11645.  
  11646.  266. Commenting Out Blocks of Code and Comments for Debugging
  11647.  
  11648.  Product Version(s): 5.10   | 5.10
  11649.  Operating System:   MS-DOS | OS/2
  11650.  Flags: ENDUSER |
  11651.  Last Modified: 29-DEC-1988    ArticleIdent: Q39312
  11652.  
  11653.  The C language does not support the use of nested comments. This might
  11654.  appear to be a limitation in cases where it is necessary,  perhaps for
  11655.  debugging purposes, to comment out a block of code which  contains
  11656.  comments. However, this situation can be overcome by using the
  11657.  much more powerful preprocessor commands #if and #endif.
  11658.  
  11659.  The #if preprocessor command evaluates a constant expression to either
  11660.  true (which has the value 1) or false (which has the value 0) to
  11661.  perform conditional compilation. If the expression equates to true,
  11662.  the code segment will be compiled. If it equates to false, it will be
  11663.  ignored by the compiler. Therefore, if the syntax below is used,
  11664.  the enclosed block of code will be forever ignored by the compiler
  11665.  giving a convenient method of effectively commenting out a block of
  11666.  code.
  11667.  
  11668.  Since the expression in the #if can be any constant expression, you
  11669.  can make complicated tests.  You can even use the /Dconst=value
  11670.  switch on the CL command line to set a preprocessor symbol which will
  11671.  include or exclude the debugging code when you compile.  This
  11672.  technique is described more fully on pages 75-77 of the Microsoft C
  11673.  Optimizing Compiler User's Guide.
  11674.  
  11675.  The following is a simple example:
  11676.  
  11677.  #define OUT 0
  11678.  
  11679.  #if OUT       /* will always equate to "false" */
  11680.  
  11681.     /* code and comments that you wish to remove are here */
  11682.  
  11683.  #endif
  11684.  
  11685.  
  11686.  267. #pragma pack() Affects Declarations, not Definitions
  11687.  
  11688.  Product Version(s): 5.00 5.10 | 5.00 5.10
  11689.  Operating System:   MS-DOS    | OS/2
  11690.  Flags: ENDUSER | S_QuickC
  11691.  Last Modified:  5-JAN-1989    ArticleIdent: Q40027
  11692.  
  11693.  Question:
  11694.  
  11695.  I need to use the preprocessor directive "#pragma pack()" to control
  11696.  how structure data are "packed" into memory. However, I don't know
  11697.  where to stick it. Should I place it before a declaration (creating a
  11698.  type) or before a definition (allocating space)?
  11699.  
  11700.  Response:
  11701.  
  11702.  The pack pragma affects declarations; not definitions. Place #pragma
  11703.  pack() prior data declarations.
  11704.  
  11705.  The following program demonstrates usage of #pragma pack():
  11706.  
  11707.  /* Elements of variables of type struct x will be byte-aligned. */
  11708.  #pragma pack(1)
  11709.  struct x { int a; char b; int c; };
  11710.  
  11711.  /* Elements of variables of type struct y will be word-aligned. */
  11712.  #pragma pack(2)
  11713.  struct y { int a; char b; int d; };
  11714.  
  11715.  /* The pragma below does NOT affect the definitions that follow. */
  11716.  #pragma pack(4)
  11717.  
  11718.  struct x X;
  11719.  struct y Y;
  11720.  
  11721.  void main (void)
  11722.  { /* dummy main */ }
  11723.  
  11724.  
  11725.  268. Error C2001: Newline in Constant for a String on Multiple Line
  11726.  
  11727.  Product Version(s): 5.00 5.10 | 5.10
  11728.  Operating System:   MS-DOS    | OS/2
  11729.  Flags: ENDUSER |
  11730.  Last Modified:  9-JAN-1989    ArticleIdent: Q40160
  11731.  
  11732.  If the program below, which contains a string literal that is
  11733.  incorrectly split over multiple lines, is compiled, the following
  11734.  error will occur:
  11735.  
  11736.     error C 2001: newline in constant
  11737.  
  11738.  The incorrect program is as follows:
  11739.  
  11740.  #include <stdio.h>
  11741.  main() {
  11742.      printf("\n %s
  11743.              %s
  11744.              %s",
  11745.              "this", "is", "it");
  11746.      }
  11747.  
  11748.  As indicated on Page 23 of the "Microsoft C for the MS-DOS Operating
  11749.  System: Language Reference" for Version 5.10, there are two methods to
  11750.  form a string that takes up more than one line.
  11751.  
  11752.  The best method is to change the format string as in the following
  11753.  example (this work because strings separated only by spaces, tabs,
  11754.  and/or newlines are concatenated):
  11755.  
  11756.  #include <stdio.h>
  11757.  main() {
  11758.      printf("\n %s"
  11759.             "%s"
  11760.             "%s",
  11761.             "this", "is", "it");
  11762.      }
  11763.  
  11764.  The older and less-prefered method is to use continuation lines by
  11765.  typing a backslash followed by a carriage return at the end of a line,
  11766.  as in the following example:
  11767.  
  11768.  printf("\n %s\
  11769.             %s\
  11770.             %s",
  11771.             "this", "is", "it");
  11772.  
  11773.  This is not as good as the previous example because the spaces at the
  11774.  beginning of the continuation line become part of the string, unlike
  11775.  example one.
  11776.  
  11777.  
  11778.  269. Simple Example Using _bios_serialcom
  11779.  
  11780.  Product Version(s): 5.00 5.10 | 5.10
  11781.  Operating System:   MS-DOS    | OS/2
  11782.  Flags: ENDUSER |
  11783.  Last Modified: 29-DEC-1988    ArticleIdent: Q39501
  11784.  
  11785.  Below is an example of using the C run-time library function
  11786.  _bios_serialcom to transmit and receive a single character over the
  11787.  serial-communications port COM1:.
  11788.  
  11789.  The _bios_serialcom routine simply calls the PC's ROM BIOS routines.
  11790.  On most PC's, these routines are not interrupt-driven nor buffered.
  11791.  As a result, characters may be lost when receiving very high-speed
  11792.  transmissions and/or if a significant amount of processing occurs
  11793.  between status checks and reads.  Although Microsoft does not provide
  11794.  interrupt-driven serial I/O routines with our C compilers, there are
  11795.  several third-parties which do.  A partial listing is available in
  11796.  the Language Support Directory which comes with the compiler.
  11797.  
  11798.  For additional information about ROM BIOS calls, please refer to "IBM
  11799.  ROM BIOS" by Ray Duncan, published by Microsoft Press. For examples of
  11800.  serial communication programs written in assembler, please refer to
  11801.  the MS-DOS Encyclopedia.
  11802.  
  11803.  The following program is a simple example which sends and receives one
  11804.  character to/from COM1:
  11805.  
  11806.  #include <stdio.h>
  11807.  #include <bios.h>
  11808.  
  11809.  void main(void)
  11810.  {
  11811.      unsigned com1_status;
  11812.      unsigned com1_send;
  11813.      unsigned com1_rec;
  11814.      unsigned com1_init;
  11815.      int result, mask;
  11816.  
  11817.      /* open serial port at 1200 baud, 8 data bits,
  11818.      ** No parity, 1 stop bit */
  11819.      com1_init = _bios_serialcom(_COM_INIT, 0,
  11820.          _COM_CHR8 | _COM_NOPARITY | _COM_STOP1 | _COM_1200);
  11821.      printf("Init status: 0x%4.4X\n", com1_init);
  11822.  
  11823.      /* send an '*' to com1 */
  11824.      com1_send = _bios_serialcom(_COM_SEND, 0, '*');
  11825.      printf("Send status: 0x%4.4X\n", com1_send);
  11826.  
  11827.      mask = 0x6100;
  11828.      /* value used to mask:
  11829.      *    bits 0-7 are related to modems,
  11830.      *    bits 8-15 are for port status,
  11831.      *      check to see that the following bits are set:
  11832.      *         8 (data ready)
  11833.      *        13 (Transmission-hold  register empty)
  11834.      *        14 (Transmission-shift register empty)
  11835.      */
  11836.  
  11837.      /* check the status */
  11838.      com1_status = _bios_serialcom(_COM_STATUS, 0, 0);
  11839.      printf("COM1 status: 0x%4.4X\n", com1_status);
  11840.  
  11841.      /* wait until a character is ready */
  11842.      do {
  11843.          /* check the status */
  11844.          com1_status = _bios_serialcom(_COM_STATUS, 0, 0);
  11845.  
  11846.          /* mask off the low order byte of com1_status */
  11847.          com1_status = com1_status & 0xFF00;
  11848.      } while( (mask & com1_status) == 0);
  11849.  
  11850.      /* get a character */
  11851.      com1_rec =  _bios_serialcom(_COM_RECEIVE, 0, 0);
  11852.      printf("Read status: 0x%4.4X\n", com1_rec);
  11853.  
  11854.      /* print the character we just received */
  11855.      result = com1_rec & 0x00FF;
  11856.      printf("Character: 0x%2.2X  =  %c\n", result, (char)result);
  11857.  }
  11858.  
  11859.  
  11860.  270. Wrong Syntax for fopen Mode Argument Gives NULL Return Value
  11861.  
  11862.  Product Version(s): 5.00 5.10 | 5.10
  11863.  Operating System:   MS-DOS    | OS/2
  11864.  Flags: ENDUSER |
  11865.  Last Modified: 29-DEC-1988    ArticleIdent: Q39602
  11866.  
  11867.  In the second argument to the fopen function, if the specification of
  11868.  the mode character t (text) or b (binary) is before the file-access
  11869.  type r (read), w (write), or a (append), no compilation errors occur.
  11870.  However, at run-time, fopen fails to open the file and returns NULL.
  11871.  
  11872.  Page 275 of the "Microsoft C Run-Time Library Reference" states that
  11873.  the mode character is to be appended to the character string for the
  11874.  type argument. If, instead, the mode character is placed before the
  11875.  beginning of the type argument, then fopen fails. An example follows.
  11876.  
  11877.  Please note that the string which is passed as the second parameter
  11878.  to fopen could be a variable string as well as a constant string.
  11879.  Since the variable string could be constructed at run-time, it is
  11880.  impossible to check for this error at compile time.
  11881.  
  11882.  Also note that strings of the form below are explicitly prohibited on
  11883.  page 275 of the C Runtime Library Reference.
  11884.  
  11885.  The program below demonstrates this behavior. It prints "failed"
  11886.  and does not open a file. If the second argument to fopen is changed
  11887.  to "wt", then it prints "succeeded" and the file is opened.
  11888.  
  11889.  The following is the program:
  11890.  
  11891.  #include <stdio.h>
  11892.  FILE *s;
  11893.  void main(void);
  11894.  void main(void)
  11895.  {
  11896.    if ((s = fopen("test.dat","tw")) == NULL)
  11897.      printf("fopen failed\n");
  11898.    else
  11899.      printf("fopen succeeded\n");
  11900.  }
  11901.  
  11902.  
  11903.  271. Example of Using Formatting with _outtext
  11904.  
  11905.  Product Version(s): 5.00 5.10
  11906.  Operating System:   MS-DOS
  11907.  Flags: ENDUSER | S_QUICKC
  11908.  Last Modified: 29-DEC-1988    ArticleIdent: Q39783
  11909.  
  11910.  When programming with the Microsoft graphics library, the printf
  11911.  function can be used, but it is not recommended. Instead, to do any
  11912.  desired formatting, the _outtext function should be used with a prior
  11913.  call to sprintf. You should not mix printf() calls with _outtext()
  11914.  calls.
  11915.  
  11916.  The user-defined _outtextf function demonstrated in the program below
  11917.  performs formatting and printing in one function. This function
  11918.  simplifies conversion of non-Microsoft C graphics-compatible source
  11919.  code to Microsoft-compatible code. An intelligent text editor could
  11920.  simply do a global search and replace "printf" to "_outtextf".
  11921.  
  11922.  This following program defines and demonstrates the function "_outtextf":
  11923.  
  11924.  #include <stdio.h>
  11925.  #include <graph.h>
  11926.  #include <stdarg.h>
  11927.  
  11928.  int _outtextf (char *format,...);
  11929.  void main (void);
  11930.  
  11931.  void main (void)
  11932.   { /* Clear the screen and display "Hello, world #87!" */
  11933.     _clearscreen (_GCLEARSCREEN);
  11934.     _outtextf ("Hello, %s #%d!","world",87);
  11935.   }
  11936.  
  11937.  int _outtextf (char *format,...)
  11938.   { va_list arglist;
  11939.     char buffer[150]; /*Must be large enough to hold formatted string*/
  11940.     int retval;
  11941.  
  11942.     va_start (arglist,format);
  11943.     retval = vsprintf(buffer,format,arglist);
  11944.     va_end (arglist);
  11945.  
  11946.     _outtext (buffer);
  11947.     return (retval);
  11948.   }
  11949.  
  11950.  
  11951.  272. "D" Incorrectly Defined as a printf/scanf Format Specifier
  11952.  
  11953.  Product Version(s): 5.00 5.10 | 5.10
  11954.  Operating System:   MS-DOS    | OS/2
  11955.  Flags: ENDUSER | docerr
  11956.  Last Modified: 29-DEC-1988    ArticleIdent: Q39784
  11957.  
  11958.  On Page 80 of the "Microsoft C 5.1 (and 5.0) Quick Reference Guide"
  11959.  (spiral bound), the capital letter "D" is incorrectly defined as a
  11960.  printf/scanf format specifier representing a signed long-decimal
  11961.  integer. The printf/scanf format specifier for a long-decimal integer
  11962.  is "ld". Using %D will print/return garbage characters.
  11963.  
  11964.  
  11965.  273. Using _getvideoconfig for Analog Monitors
  11966.  
  11967.  Product Version(s): 5.10
  11968.  Operating System:   MS-DOS
  11969.  Flags: ENDUSER | s_quickc
  11970.  Last Modified: 17-MAY-1989    ArticleIdent: Q43536
  11971.  
  11972.  In the Microsoft C 5.10 Optimizing Compiler Run-Time Library, the
  11973.  function _getvideoconfig does not make a distinction between an analog
  11974.  color monitor and an analog monochrome monitor. For both of these
  11975.  configurations, it puts the value _ANALOG in the "monitor" field of
  11976.  the struct "videoconfig." _ANALOG is a manifest constant defined in
  11977.  the include file GRAPH.H to be 0x0018.
  11978.  
  11979.  The function _getvideoconfig is enhanced in QuickC Version 2.00 so
  11980.  that it recognizes analog monitors as being color or monochrome.
  11981.  There are two additional manifest constants defined in the new
  11982.  GRAPH.H: _ANALOGCOLOR (defined to be 0x0010) and _ANALOGMONO
  11983.  (0x0008).
  11984.  
  11985.  
  11986.  274. Time Functions Calculate for Daylight Savings Time
  11987.  
  11988.  Product Version(s): 5.00   | 5.10
  11989.  Operating System:   MS-DOS | OS/2
  11990.  Flags: ENDUSER |
  11991.  Last Modified: 30-DEC-1988    ArticleIdent: Q39908
  11992.  
  11993.  The Microsoft time functions calculate for daylight savings time. In
  11994.  particular, mktime will set the hour ahead or back one hour according
  11995.  to the rules of daylight savings time. The only way to change the
  11996.  dates that the time functions use in calculating daylight savings time
  11997.  is to get the run-time library source code available for the time
  11998.  functions and modify the routine _isindst() in the file tzset.c.
  11999.  
  12000.  
  12001.  275. _scanf and _cscanf always Echo to the Screen
  12002.  
  12003.  Product Version(s): 5.10
  12004.  Operating System:   MS-DOS
  12005.  Flags: ENDUSER |
  12006.  Last Modified: 30-DEC-1988    ArticleIdent: Q39909
  12007.  
  12008.  The following is on Page 177 of the "Microsoft C 5.1 Optimizing
  12009.  Compiler Run-Time Library Reference" manual:
  12010.  
  12011.     Note:
  12012.     While scanf normally echoes the input character, it will not
  12013.     do so if the last call was to ungetch.
  12014.  
  12015.  This process does not appear to work correctly. The following code
  12016.  sample uses _getch() to get a character from the keyboard, then calls
  12017.  _ungetch(ch) to disable echoing to the screen before calling _cscanf.
  12018.  The keyboard input echoes to the screen regardless of the call to
  12019.  _ungetch. If _cscanf is replaced with _scanf, it still echoes to the
  12020.  screen.
  12021.  
  12022.  The following program calls _ungetch, then echoes the filename to
  12023.  the screen when it is read by _scanf; although, according to the
  12024.  documentation, it should not echo:
  12025.  
  12026.  ------------------------------------------------------------
  12027.  #include <conio.h>
  12028.  #include <stdio.h>
  12029.  #include <ctype.h>
  12030.  
  12031.  int result;                   /* return value from _scanf */
  12032.  char buff2[20];               /* buffer for filename */
  12033.  int ch;                       /* character returned by _getch*/
  12034.  
  12035.  main()                        /* begin executable code */
  12036.  
  12037.  {
  12038.  ch = getch();                 /* read a keyboard character */
  12039.  
  12040.  cprintf ("please enter file name");
  12041.  ungetch(ch);                  /* call to _ungetch */
  12042.  result = scanf("%19s", buff2);                 /* call _scanf */
  12043.  printf ("\n Number of correctly matched input"
  12044.         "items =  %d\n", result);          /* print # of input items */
  12045.         }
  12046.  
  12047.  
  12048.  276. C4047 Error Message when Initializing Unions
  12049.  
  12050.  Product Version(s): 5.10
  12051.  Operating System:   MS-DOS
  12052.  Flags: ENDUSER |
  12053.  Last Modified: 30-DEC-1988    ArticleIdent: Q39910
  12054.  
  12055.  If an attempt is made to initialize the second element of a union at
  12056.  declaration time (rather than in the code), the following warning
  12057.  is generated:
  12058.  
  12059.     C4047:'initialization' - different levels of indirection
  12060.  
  12061.  This error conforms to the ANSI standard, which assumes that the
  12062.  initialization is directed at the first element of the union, and
  12063.  reports, therefore, that the initializing values are of an incorrect
  12064.  type. If an attempt is made to initialize both the first and second
  12065.  element at declaration time, the same warning results.
  12066.  
  12067.  The following program demonstrates this error:
  12068.  
  12069.  -----------------------------------------------------------------
  12070.  union TEST {
  12071.      struct{
  12072.        int a;
  12073.        int b;
  12074.        int c;
  12075.      } one;             /* union element #1 */
  12076.      struct {
  12077.        char *ptr1;
  12078.        char *ptr2;
  12079.        char *ptr3;
  12080.        char *ptr4;
  12081.     } two;             /* union element #2 */
  12082.  }u;
  12083.  
  12084.  char ch1[10], ch2[10], ch3[10],ch4[10] ;
  12085.  
  12086.  union TEST test ={{1,2,3},    /* initialize element #1*/
  12087.                     {ch1,ch2,ch3,ch4} /* attempt to initialize #2 */
  12088.                     };
  12089.  
  12090.  main()
  12091.  {
  12092.  }
  12093.  ----------------------------------------------------------------
  12094.  
  12095.  The above program fails with the error C4047. The following
  12096.  initialization also fails with the same error:
  12097.  
  12098.     union TEST test = {ch1,ch2,ch3,ch4}
  12099.  
  12100.  However, an attempt to initialize the first element of the union will
  12101.  be successful, as follows:
  12102.  
  12103.     union TEST test = {1,2,3}
  12104.  
  12105.  If it is necessary to initialize the second element of a union, we
  12106.  suggest that you change the order of your union members, so that the
  12107.  element that requires initialization appears as the first element of
  12108.  the union.
  12109.  
  12110.  
  12111.  277. C 5.10 Setup Gives U1203 Error under DOS Versions 2.x
  12112.  
  12113.  Product Version(s): 5.10
  12114.  Operating System:   MS-DOS
  12115.  Flags: ENDUSER |
  12116.  Last Modified: 30-DEC-1988    ArticleIdent: Q39911
  12117.  
  12118.  When running the setup program for C Version 5.10 under DOS Versions 2.x,
  12119.  the following error is generated:
  12120.  
  12121.     U1203    : invalid object module
  12122.  
  12123.  This error occurs because the library manager, LIB.EXE, is bound.
  12124.  Under DOS Versions 2.x, bound programs can only be run from within the
  12125.  current working directory. Giving an fully qualified path will cause
  12126.  the error.
  12127.  
  12128.  Moving LIB.EXE into the current directory may avoid this problem.
  12129.  
  12130.  More information will be posted as it becomes available.
  12131.  
  12132.  
  12133.  278. Misleading Information about Linker Options with /link
  12134.  
  12135.  Product Version(s): 5.00 5.10 | 5.10
  12136.  Operating System:   MS-DOS    | OS/2
  12137.  Flags: ENDUSER |
  12138.  Last Modified: 30-DEC-1988    ArticleIdent: Q39915
  12139.  
  12140.  Pages 120-123 of the "Microsoft C 5.1 Optimizing Compiler User's
  12141.  Guide" describe options that can be used with the linker. The manual
  12142.  states that these options have equivalent options that can be used on
  12143.  the compiler command line. This subject can be confusing.
  12144.  
  12145.  If you are compiling and linking through the CL driver, then compile
  12146.  options are available to pass options to the link command line. For
  12147.  example, the /Fm option passes the /MAP option to the linker and a
  12148.  map file is produced.
  12149.  
  12150.  If a compiler option is not available for the linker option you want
  12151.  to pass to the link command line, the /link compile option can be
  12152.  used. The linker option can be given after /link option on the CL
  12153.  command line.
  12154.  
  12155.  
  12156.  279. Using _dos_findfirst to Get the Time and Date
  12157.  
  12158.  Product Version(s): 5.10   | 5.10
  12159.  Operating System:   MS-DOS | OS/2
  12160.  Flags: ENDUSER |  s_quickc
  12161.  Last Modified: 30-DEC-1988    ArticleIdent: Q39916
  12162.  
  12163.  The code below illustrates how to extract the time and the date out of
  12164.  the C run-time function _dos_findfirst. The program prints out the
  12165.  time and the date of the creation of the file "test".
  12166.  
  12167.  This information also applies to QuickC.
  12168.  
  12169.  The time at which the file was last written is returned as a binary
  12170.  value in a word formatted as follows:
  12171.  
  12172.     Bits     Meaning
  12173.  
  12174.     0-4      Number of seconds DIVIDED BY TWO
  12175.          (to find actual number of seconds, multiply by two)
  12176.     5-10     Minutes
  12177.     11-15    Hours, based on a 24-hour clock
  12178.  
  12179.  The date at which the file was last written is returned as a binary
  12180.  value in a word formatted as follows:
  12181.  
  12182.     Bits     Meaning
  12183.  
  12184.     0-4      Day of the month
  12185.     5-8      Month (1 = January and so on)
  12186.     9-15     Number of the year minus 1980
  12187.  
  12188.  The following is a sample code:
  12189.  
  12190.  #include <dos.h>
  12191.  #include <stdio.h>
  12192.  
  12193.  struct {
  12194.    unsigned biseconds: 5;  /* in units of TWO seconds */
  12195.    unsigned minutes: 6;
  12196.    unsigned hours:   5;
  12197.  } *ptime;
  12198.  
  12199.  struct{
  12200.    unsigned day:   5;
  12201.    unsigned month: 4;
  12202.    unsigned year:  7;
  12203.  } *pdate;
  12204.  
  12205.  struct find_t c_file;
  12206.  
  12207.  main()
  12208.  {
  12209.     _dos_findfirst ("test", _A_NORMAL, &c_file);
  12210.  
  12211.     system("cls");
  12212.  
  12213.     ptime = &c_file.wr_time;
  12214.     pdate = &c_file.wr_date;
  12215.  
  12216.     printf ("Created at %u:%u:%u",\
  12217.              ptime->hours, ptime->minutes, ptime->seconds * 2);
  12218.          /* NOTE: seconds are divided by two when stored,
  12219.               so we have to multiply by two to get
  12220.               the proper value.... */
  12221.  
  12222.     printf ("on %u-%u-%u.",\
  12223.              pdate->month, pdate->day, pdate->year);
  12224.  }
  12225.  
  12226.  The program might produce the following output (depending on when the
  12227.  file "test" was created):
  12228.  
  12229.     Created at 10:32:28 on 12-19-8
  12230.  
  12231.  Note that the seconds field of the time will always be even.
  12232.  
  12233.  For more information on function _dos_findfirst, see "Microsoft C 5.1
  12234.  Optimizing Compiler Run-Time Library Reference," starting on Page 194.
  12235.  
  12236.  
  12237.  280. Open() Will Not Ignore Append Path
  12238.  
  12239.  Product Version(s): 5.00 5.10
  12240.  Operating System:   MS-DOS
  12241.  Flags: ENDUSER | s_quickc
  12242.  Last Modified:  9-JAN-1989    ArticleIdent: Q40183
  12243.  
  12244.  DOS allows you to set an APPEND path to locate data files. Microsoft C
  12245.  library functions such as open and fopen will not ignore the APPEND
  12246.  statement, even if a full pathname is given to the specific function.
  12247.  This is expected behavior. If you wish to have the APPEND path
  12248.  ignored, you will have to write your own low-level open function, or
  12249.  ensure that the APPEND path is removed before your program is run.
  12250.  
  12251.  
  12252.  281. LINK4 Is Not Included in C 5.10 or MASM 5.10 Packages
  12253.  
  12254.  Product Version(s): 5.10   | 5.10
  12255.  Operating System:   MS-DOS | OS/2
  12256.  Flags: ENDUSER | h_masm PMWIN
  12257.  Last Modified: 13-JAN-1989    ArticleIdent: Q40236
  12258.  
  12259.  LINK.EXE, the incremental linker provided with the Windows Software
  12260.  Development Kit for DOS, is not included with C Version 5.10 or MASM
  12261.  Version 5.10, contrary to the statement on Page 82 of the January 1989
  12262.  issue of the "Microsoft Systems Journal."
  12263.  
  12264.  A bound linker, LINK.EXE Version 5.01.20, which may be used under DOS
  12265.  or OS/2, comes with MASM Version 5.10 as well as the real-mode linker
  12266.  Version 3.64 for DOS only. The C Version 5.10 retail package comes with
  12267.  the bound linker Version 5.01.21 and the real-mode linker Version
  12268.  3.65.
  12269.  
  12270.  To link under OS/2, use the bound linker with the latest version
  12271.  number you have available. To prepare for incremental linking with the
  12272.  ILINK.EXE utility under OS/2, use LINK.EXE with the option /INC. See
  12273.  the C Version 5.10 "Update (CodeView and Utility)" section of the
  12274.  "Microsoft C 5.1 Optimizing Compiler CodeView and Utilities" manual,
  12275.  or the "Microsoft Macro Assembler 5.1 Updates and Microsoft Editor"
  12276.  manual for more information on incremental linkage and the ILINK.EXE
  12277.  utility.
  12278.  
  12279.  LINK with /INC and ILINK have failed to work correctly for Windows
  12280.  program development under DOS, contrary to our documentation. DOS
  12281.  Windows developers should use LINK4, which comes with the Windows SDK.
  12282.  
  12283.  The ILINK utility should only be used under OS/2 for creating OS/2
  12284.  programs.
  12285.  
  12286.  
  12287.  
  12288.  282. Accessing I/O Ports under OS/2 Protected Mode
  12289.  
  12290.  Product Version(s): 5.10
  12291.  Operating System:   OS/2
  12292.  Flags: ENDUSER | COM1 COM2 serial communication
  12293.  Last Modified:  5-JAN-1989    ArticleIdent: Q39973
  12294.  
  12295.  Problem:
  12296.  
  12297.  I am trying to use the inp(), inpw(), outp(), and outpw() routines in
  12298.  the Microsoft C Version 5.10 run-time library. Every time I run my
  12299.  program I get the following message:
  12300.  
  12301.     SYS1943: A program caused a protection violation.
  12302.  
  12303.  Response:
  12304.  
  12305.  To read from or write to ports under OS/2 protected mode you must have
  12306.  a .DEF module-definition file that gives IOPL (input/output privilege)
  12307.  to the _IOSEG segment. Also, if the intrinsic (/Oi) switch is used
  12308.  during compilation, the segments that contain the port functions must
  12309.  be given IOPL. You can check the .MAP file for the associated segment
  12310.  name or compile with the /NT switch to manually name the segment.
  12311.  
  12312.  The following must be in your .DEF file if /Oi was not used:
  12313.  
  12314.  SEGMENTS
  12315.      _IOSEG CLASS 'IOSEG_CODE' IOPL
  12316.  
  12317.  If /Oi was used, the following must be in your .DEF file:
  12318.  
  12319.  SEGMENTS
  12320.      (segment name) IOPL
  12321.  
  12322.  Note: Segments that have IOPL cannot make system calls. If you do,
  12323.  you will generate a GP fault, a general protection violation. This
  12324.  behavior is discussed on Page 239 of Letwin's "Inside OS/2."
  12325.  
  12326.  
  12327.  283. Error C2177: Constant Too Big
  12328.  
  12329.  Product Version(s): 5.10   | 5.10
  12330.  Operating System:   MS-DOS | OS/2
  12331.  Flags: ENDUSER | s_quickc
  12332.  Last Modified:  9-JAN-1989    ArticleIdent: Q39974
  12333.  
  12334.  The code below produces compiler error "C2177 : constant too big,"
  12335.  even though variable p is an unsigned long. The compiler does not
  12336.  generate this error if the number is 2,147,483,647 (maximum signed
  12337.  long possible) or less. Casting p to an unsigned long or putting L
  12338.  (for long) on the end of the number had no effect.
  12339.  
  12340.  This information also applies to QuickC.
  12341.  
  12342.  The following example demonstrates the error:
  12343.  
  12344.  #include <stdio.h>
  12345.  main()
  12346.  {
  12347.    unsigned long p;
  12348.    p = 4294967295;      /* maximum unsigned long */
  12349.    printf("%lu is the maximum unsigned long.",p);
  12350.  }
  12351.  
  12352.  According to the include file limits.h, to declare something as
  12353.  unsigned long, one must use the hexadecimal form if the number will be
  12354.  greater than 2,147,483,647. The code should be changed to the following:
  12355.  
  12356.  #include <stdio.h>
  12357.  main()
  12358.  {
  12359.    unsigned long p;
  12360.    p = 0xffffffff;
  12361.    printf("%lu is the maximum unsigned long.",p);
  12362.  }
  12363.  
  12364.  The code will produce the following output:
  12365.  
  12366.     4294967295 is the maximum unsigned long.
  12367.  
  12368.  
  12369.  284. Dynamic Allocation for Two Dimensional Arrays
  12370.  
  12371.  Product Version(s): 4.00 5.x | 5.10
  12372.  Operating System:   MS-DOS   | OS/2
  12373.  Flags: ENDUSER | s_quickc
  12374.  Last Modified:  4-JAN-1989    ArticleIdent: Q39976
  12375.  
  12376.  Question:
  12377.  
  12378.  How can I dynamically allocate memory for a two dimensional array?
  12379.  
  12380.  Response:
  12381.  
  12382.  The best method depends on the flexibility needed and the amount of
  12383.  information concerning the array known at coding time. The examples
  12384.  below set up two dimensional arrays of characters. Any element can be
  12385.  accessed with double sub-scripts, such as array[i][j]. Symbols in
  12386.  uppercase are constants, while those in lowercase are variables.
  12387.  
  12388.  If one of the dimensions of the array is known, either of the
  12389.  following two methods can be used. The first example creates more
  12390.  overhead due to the number of malloc calls, but it is more flexible
  12391.  because each malloc can be of a different size.
  12392.  
  12393.  The following is the first example:
  12394.  
  12395.      char *array[DIM_ONE];
  12396.      int   i;
  12397.  
  12398.      for (i = 0; i < DIM_ONE; i++) {
  12399.          array[i] = (char *)malloc(sizeof(char) * dim_two);
  12400.          if (array[i] == NULL) {
  12401.              printf("Not enough memory for columns in row %d!\n", i);
  12402.              exit(1);
  12403.          }
  12404.      }
  12405.  
  12406.  The following is the second example:
  12407.  
  12408.      char *array[DIM_ONE];
  12409.      int   i;
  12410.  
  12411.      array[0] = (char *)malloc(sizeof(char) * DIM_ONE * dim_two);
  12412.      if (array[0] == NULL) {
  12413.          printf("Not enough memory for columns!\n");
  12414.          exit(1);
  12415.      }
  12416.      for (i = 1; i < DIM_ONE; i++) {
  12417.          array[i] = (array[0] + (i * dim_two));
  12418.      }
  12419.  
  12420.  If neither of the dimensions is known at coding time, one of the
  12421.  following two methods can be used. The pros and cons of each example
  12422.  are the same as those for the previous examples.
  12423.  
  12424.  The following is the third example:
  12425.  
  12426.      char **array;
  12427.      int    i;
  12428.  
  12429.      array = (char **)malloc(sizeof(char *) * dim_one);
  12430.      if (array == NULL) {
  12431.          printf("Not enough memory for rows!\n");
  12432.          exit(1);
  12433.      }
  12434.      for (i = 0; i < dim_one; i++) {
  12435.          array[i] = (char *)malloc(sizeof(char) * dim_two);
  12436.          if (array[i] == NULL) {
  12437.              printf("Not enough memory for columns in row %d!\n", i);
  12438.              exit(1);
  12439.          }
  12440.      }
  12441.  
  12442.  The following is the fourth example:
  12443.  
  12444.      char **array;
  12445.      int    i;
  12446.  
  12447.      array = (char **)malloc(sizeof(char *) * dim_one);
  12448.      if (array == NULL) {
  12449.          printf("Not enough memory for rows!\n");
  12450.          exit(1);
  12451.      }
  12452.      array[0] = (char *)malloc(sizeof(char) * dim_one * dim_two);
  12453.      if (array[0] == NULL) {
  12454.          printf("Not enough memory for columns!\n");
  12455.          exit(1);
  12456.      }
  12457.      for (i = 1; i < dim_one; i++) {
  12458.          array[i] = (array[0] + (i * dim_two));
  12459.      }
  12460.  
  12461.  
  12462.  285. Chmod() on an Open File
  12463.  
  12464.  Product Version(s): 5.00 5.10
  12465.  Operating System:   MS-DOS
  12466.  Flags: ENDUSER | s_quickc
  12467.  Last Modified: 16-MAY-1989    ArticleIdent: Q40349
  12468.  
  12469.  When a file has been opened, it is not valid to perform a chmod() on
  12470.  the file. Although some operating systems (for example, UNIX) allow a
  12471.  program to change the permission of a file while it it open, MS-DOS
  12472.  requires the file to be closed before performing this function.
  12473.  Unusual results can occur, particularly when SHARE.EXE is installed,
  12474.  if an attempt is made to chmod() on an open file. One of the results
  12475.  is an error indicating the file is full, when only 1 byte is written
  12476.  to an empty file.
  12477.  
  12478.  
  12479.  286. _getimage Buffer May Be Huge (Larger than 64K)
  12480.  
  12481.  Product Version(s): 5.00 5.10
  12482.  Operating System:   MS-DOS
  12483.  Flags: ENDUSER | S_QuickC
  12484.  Last Modified: 16-JAN-1989    ArticleIdent: Q40350
  12485.  
  12486.  The graphics functions _getimage and _putimage may be used to store
  12487.  and display graphic images that require a buffer size larger than 64K.
  12488.  Even though these functions specify that the storage buffer is a far
  12489.  pointer, _getimage and _putimage internally treat the buffer as huge
  12490.  and do 32-bit address arithmetic.
  12491.  
  12492.  The following program demonstrates using the image functions on a huge
  12493.  image.
  12494.  
  12495.  /********************************************************************
  12496.   * Example program to demonstrate using the functions _getimage and *
  12497.   * _putimage on a huge image.                                       *
  12498.   ********************************************************************/
  12499.  
  12500.  #include <stddef.h>
  12501.  #include <malloc.h>
  12502.  #include <process.h>
  12503.  #include <graph.h>
  12504.  
  12505.  void main (void)
  12506.   { long size;
  12507.     char far *image;
  12508.  
  12509.     /* Put the display in a VGA mode and allocate a huge buffer. */
  12510.     if (_setvideomode(_VRES16COLOR)==0)
  12511.         { _outtext ("Video mode not supported!\n");
  12512.           exit (0);
  12513.         }
  12514.  
  12515.     /* In _VRES16COLOR, size is 153604. */
  12516.     size = _imagesize(0,0,639,479);
  12517.  
  12518.     if ( (image=halloc(size,1)) == NULL)
  12519.         { _outtext ("Not enough memory for buffer!\n");
  12520.           exit (0);
  12521.         }
  12522.  
  12523.     /* Draw a couple shapes and capture the screen. */
  12524.     _ellipse (_GBORDER,0,0,639,479);
  12525.     _rectangle (_GBORDER,0,0,639,479);
  12526.     _getimage (0,0,639,479,image);
  12527.  
  12528.     /* Clear the screen and redraw the image. */
  12529.     _clearscreen (_GCLEARSCREEN);
  12530.     _putimage (0,0,image,_GOR);
  12531.  
  12532.     hfree (image);
  12533.   }
  12534.  
  12535.  
  12536.  287. Call _setvideomode before Calling _imagesize
  12537.  
  12538.  Product Version(s): 5.00 5.10
  12539.  Operating System:   MS-DOS
  12540.  Flags: ENDUSER | S_QuickC
  12541.  Last Modified: 16-JAN-1989    ArticleIdent: Q40351
  12542.  
  12543.  Problem:
  12544.  
  12545.  I am using the _imagesize function to determine the size required to
  12546.  store a graphics image. However, this function is not returning the
  12547.  expected result.
  12548.  
  12549.  Response:
  12550.  
  12551.  The _imagesize function calls _getvideoconfig to determine the number
  12552.  of bits required to store a pixel given the CURRENT video mode. If you
  12553.  are calling _imagesize prior to calling _setvideomode, an unexpected
  12554.  result is returned by _imagesize.
  12555.  
  12556.  In summary, do the following in order:
  12557.  
  12558.  1. _setvideomode
  12559.  
  12560.  2. _imagesize
  12561.  
  12562.  3. _getimage and putimage
  12563.  
  12564.  
  12565.  288. Operation of scanf When Using the Width Option in the Format
  12566.  
  12567.  Product Version(s): 5.10   | 5.10
  12568.  Operating System:   MS-DOS | OS/2
  12569.  Flags: ENDUSER |
  12570.  Last Modified: 17-MAY-1989    ArticleIdent: Q40357
  12571.  
  12572.  The scanf run-time library function under Microsoft C allows the
  12573.  specification of the width that you would like to read in from the
  12574.  input device. Some examples of this width formatting are as follows:
  12575.  
  12576.     scanf ("%10s", buffer);   /* read ten chars into buffer[] */
  12577.     scanf ("%5d", &i);     /* read five digits of a number into i */
  12578.  
  12579.  When using width parameters in the format, the first n digits are read
  12580.  into the address specified.
  12581.  
  12582.  When used with a character string, the width parameter performs as
  12583.  follows:
  12584.  
  12585.     char buffer[15];
  12586.     scanf ("%10s", buffer);
  12587.  
  12588.  The first 10 characters are read, and a NULL terminator is added to
  12589.  the end of the string.
  12590.  
  12591.  When used with an integer or float, scanf always reads the first n
  12592.  characters (including decimal if in a float) specified with the width
  12593.  format. Entering Invalid characters (e.g. a decimal in an integer, any
  12594.  alphabetic character) causes the termination and failure of the read.
  12595.  
  12596.  
  12597.  289. Bit-Shift Function in C
  12598.  
  12599.  Product Version(s): 5.10    | 5.10
  12600.  Operating System:   MS-DOS  | OS/2
  12601.  Flags: ENDUSER | s_quickc
  12602.  Last Modified: 16-MAY-1989    ArticleIdent: Q40358
  12603.  
  12604.  Question:
  12605.  
  12606.  How do I rotate, rather than shift, bits in a word? I don't want to
  12607.  lose any bits as happens when I shift.
  12608.  
  12609.  Response:
  12610.  
  12611.  Use the _rotl and _rotr functions in the C Runtime Library. These
  12612.  are described in the "Microsoft C Run-Time Library Reference."
  12613.  
  12614.  
  12615.  290. Turning the Scroll Lock On
  12616.  
  12617.  Product Version(s): 5.00 5.10 | 5.10
  12618.  Operating System:   MS-DOS    | OS/2
  12619.  Flags: ENDUSER | s_quickc
  12620.  Last Modified: 16-JAN-1989    ArticleIdent: Q40359
  12621.  
  12622.  The following code illustrates how to turn the Scroll Lock on in
  12623.  your program. Note: This code is only for use under DOS. Running
  12624.  it under OS/2 will cause a protection violation. Use the OS/2
  12625.  FAPI function KbdSetStatus to set the status of shift flags when
  12626.  writing programs which will run under OS/2 or be bound to run under
  12627.  both DOS and OS/2.
  12628.  
  12629.  #include <stdio.h>
  12630.  main()
  12631.  {
  12632.     /* Get the address of the keyboard status byte */
  12633.     char far *kbdstat=0x00000417L;
  12634.  
  12635.     char scrollmask=0x10;
  12636.  
  12637.     /* OR *kbdstat with scrollmask to set bit 4 in the
  12638.        keyboard status byte to 1 */
  12639.  
  12640.     *kbdstat= *kbdstat | scrollmask;
  12641.  }
  12642.  
  12643.  Additional information on keyboard status can be found in the Peter
  12644.  Norton "Programmer's Guide to the IBM PC and PS/2." The above information
  12645.  also applies to QuickC.
  12646.  
  12647.  
  12648.  291. Incomplete Memory Model Switch in User's Guide Example
  12649.  
  12650.  Product Version(s): 5.00 5.10 | 5.10
  12651.  Operating System:   MS-DOS    | OS/2
  12652.  Flags: ENDUSER | docerr
  12653.  Last Modified: 16-MAY-1989    ArticleIdent: Q40375
  12654.  
  12655.  The following compile command line given on Page 158, Section 6.7, of
  12656.  the "Microsoft C 5.1 Optimizing Compiler User's Guide" is incorrect:
  12657.  
  12658.     CL /As /Au /ND DATA1 PROG1.C
  12659.  
  12660.  This line should read as follows:
  12661.  
  12662.     CL /AS /Au /ND DATA1 PROG1.C
  12663.  
  12664.  If a program is compiled with /As rather than /AS, the following error
  12665.  will be issued:
  12666.  
  12667.     Command line error : D2013 incomplete model specification
  12668.  
  12669.  This error occurs because the data pointer size has not been
  12670.  specified.
  12671.  
  12672.  
  12673.  292. Warning C4051 Generated by Clock Function in C
  12674.  
  12675.  Product Version(s): 5.10   | 5.10
  12676.  Operating System:   MS-DOS | OS/2
  12677.  Flags: ENDUSER | s_QuickC docerr
  12678.  Last Modified: 16-MAY-1989    ArticleIdent: Q40376
  12679.  
  12680.  The example on Page 167 of the "Microsoft C 5.1 Optimizing Compiler
  12681.  Run-Time Library Reference" that shows how to use the run-time library
  12682.  function clock produces a warning C4051 : data conversion. The warning
  12683.  is generated because the variable tm is defined as an integer while
  12684.  clock_t is defined as a long in the include file time.h.
  12685.  
  12686.  As a result, warning C4051 is generated on the following line:
  12687.  
  12688.     if ((tm=clock()) != (clock_t)-1)
  12689.  
  12690.  To eliminate this warning, declare variable tm as a long.
  12691.  
  12692.  Also, if you want to see the elapsed time as real numbers, the
  12693.  following line should be changed:
  12694.  
  12695.     printf("Processor time equals %d second\n", tm/CLK_TCK)
  12696.  
  12697.  The line above should be changed to the following:
  12698.  
  12699.     printf("Processor time equals %fsecond\n",tm/(float)CLK_TCK)
  12700.  
  12701.  
  12702.  293. Problems with Using the Digital Output of a VGA Adapter
  12703.  
  12704.  Product Version(s): 5.00 5.10
  12705.  Operating System:   MS-DOS
  12706.  Flags: ENDUSER | S_QUICKC
  12707.  Last Modified: 16-MAY-1989    ArticleIdent: Q40573
  12708.  
  12709.  Problem:
  12710.  
  12711.  When I run programs, such as GRDEMO, that call the graphics function
  12712.  _setvideomode, a border is displayed around my monitor. Also, the
  12713.  functions _remappalette and _remapallpalette do not seem to work
  12714.  correctly.
  12715.  
  12716.  Response:
  12717.  
  12718.  Some VGA display adapters have analog- and digital-output
  12719.  capabilities. The above behavior occurs when the digital output of a
  12720.  VGA display adapter is connected to the monitor.
  12721.  
  12722.  When the digital output is connected to an ECD (EGA monitor), a green
  12723.  border is observed. When the digital output is connected to a
  12724.  multisync class monitor, a gray border is observed. In either case,
  12725.  remapping the palette does not function. When the analog output is
  12726.  connected to a multisync or VGA monitor, the correct behavior is
  12727.  observed.
  12728.  
  12729.  The problem is that the graphics adapter is rightfully determined to
  12730.  be VGA class -- although for practical purposes it is really EGA
  12731.  class. At this point, the C graphics library treats the display
  12732.  incorrectly as VGA. Connecting a digital monitor to the digital output
  12733.  of a VGA adapter is a non-standard hardware configuration (the digital
  12734.  output of a VGA graphics adapter is non-standard). The behavior of a
  12735.  non-standard hardware configuration is unpredictable.
  12736.  
  12737.  
  12738.  
  12739.  294. You Cannot Trap CTRL+ALT+DEL in OS/2
  12740.  
  12741.  Product Version(s): 5.10
  12742.  Operating System:   OS/2
  12743.  Flags: ENDUSER |
  12744.  Last Modified: 16-MAY-1989    ArticleIdent: Q40580
  12745.  
  12746.  In OS/2, you cannot trap the CTRL+ALT+DEL. This key sequence is caught
  12747.  by the keyboard driver and never makes it into the input steam, so you
  12748.  have no access to it.
  12749.  
  12750.  
  12751.  295. Overlays and BINDing Are Not Compatible
  12752.  
  12753.  Product Version(s): 5.10   | 5.10
  12754.  Operating System:   MS-DOS | OS/2
  12755.  Flags: ENDUSER |
  12756.  Last Modified: 25-MAY-1989    ArticleIdent: Q40581
  12757.  
  12758.  Question:
  12759.  
  12760.  I have written a large program that needs to be overlaid to run in
  12761.  DOS. Is there a way I can compile it for OS/2, then BIND it to run in
  12762.  DOS with overlays so that I only have a single executable for both
  12763.  OS/2 and DOS?
  12764.  
  12765.  Response:
  12766.  
  12767.  You cannot do this; to BIND a program to run in DOS, you need a
  12768.  protected-mode executable. However, protected-mode executables do not
  12769.  understand overlays. As a result, there is no way to BIND a program
  12770.  that needs overlays in DOS. You have to have two different
  12771.  executables.
  12772.  
  12773.  Note: The two executables could be combined into one large executable
  12774.  by creating the real-mode executable and naming it in the STUB
  12775.  statement in the .DEF file when linking the OS/2 application. There is
  12776.  no real advantage to this; however, the new .EXE file will be a little
  12777.  larger than the two separate files. The STUB statement is documented
  12778.  by the C 5.10 utilities update in the LINK section.
  12779.  
  12780.  
  12781.  296. Floating-Point Routines Are Not Reentrant
  12782.  
  12783.  Product Version(s): 5.10
  12784.  Operating System:   MS-DOS
  12785.  Flags: ENDUSER |
  12786.  Last Modified: 25-MAY-1989    ArticleIdent: Q40587
  12787.  
  12788.  Even if you only want simple arithmetic operations, the 80x87 chip
  12789.  doesn't provide a means for saving and restoring all of its registers.
  12790.  Microsoft wrote its library routines for DOS, which for the most part
  12791.  handle single-process routines, and therefore do not provide the
  12792.  routines necessary for achieving this effect with the coprocessor
  12793.  chip.
  12794.  
  12795.  If you want to develop a program that requires the coprocessor to be
  12796.  reentrant, you must provide your own routines that save and restore
  12797.  the registers of the coprocessor.
  12798.  
  12799.  
  12800.  297. Search Order for Include Files When Using APPEND Command
  12801.  
  12802.  Product Version(s): 5.00 5.10
  12803.  Operating System:   MS-DOS
  12804.  Flags: ENDUSER | append include
  12805.  Last Modified: 25-MAY-1989    ArticleIdent: Q40588
  12806.  
  12807.  A data file path can be specified in DOS by using the APPEND command.
  12808.  DOS searches for a data file using the APPEND path. A file included by
  12809.  a C program can be in a directory that is in the data file path. The C
  12810.  compiler searches for the include file in the following order:
  12811.  
  12812.  1. Current directory
  12813.  
  12814.  2. Directories specified by the INCLUDE environment variable
  12815.  
  12816.  3. Directories specified by the APPEND command
  12817.  
  12818.  Please refer to your DOS documentation for specific information about
  12819.  using the APPEND command.
  12820.  
  12821.  Note: The APPEND command can cause other problems during
  12822.  compilation, linking, and execution. Microsoft recommends not using
  12823.  the APPEND command when developing C programs.
  12824.  
  12825.  
  12826.  298. The Definition of Reentrancy
  12827.  
  12828.  Product Version(s): 4.00 5.00 5.10
  12829.  Operating System:   MS-DOS
  12830.  Flags: ENDUSER | re-entrant reentrant
  12831.  Last Modified: 16-MAY-1989    ArticleIdent: Q40589
  12832.  
  12833.  Question:
  12834.  
  12835.  What is reentrancy?
  12836.  
  12837.  Response:
  12838.  
  12839.  Reentrancy is the ability of code to be executed simultaneously by
  12840.  more than one process. It requires that the code not change the state
  12841.  of any global object, such as global variables or hardware. Any code
  12842.  compiled by the C compiler that uses only automatic variables will be
  12843.  reentrant only if the library functions used by the code are also
  12844.  reentrant.
  12845.  
  12846.  Note: Most library routines are not reentrant, nor is DOS or BIOS.
  12847.  
  12848.  
  12849.  299. Operator sizeof Returns Type size_t Defined as Unsigned int
  12850.  
  12851.  Product Version(s): 5.00 5.10 | 5.10
  12852.  Operating System:   MS-DOS    | OS/2
  12853.  Flags: ENDUSER | docerr
  12854.  Last Modified: 11-JAN-1990    ArticleIdent: Q40590
  12855.  
  12856.  The sizeof operator returns a value that is of type size_t. The
  12857.  definition of size_t is implementation dependent, according to the
  12858.  ANSI standard. In Microsoft C, the size_t type is defined in STDDEF.H
  12859.  and in MALLOC.H as an unsigned int. This is documented on Pages 38 and
  12860.  98 of the "Microsoft C Optimizing Compiler Run-Time Library Reference"
  12861.  manual.
  12862.  
  12863.  The reference manual describes the sizeof operator on Pages 120-121,
  12864.  Section 5.3.4, but does not give the return type.
  12865.  
  12866.  The index entry for "size_t type" incorrectly lists Pages 38 and 97;
  12867.  it should say 38 and 98.
  12868.  
  12869.  
  12870.  300. Misspelling "Default" Gives No Error
  12871.  
  12872.  Product Version(s): 5.00 5.10 | 5.10
  12873.  Operating System:   MS-DOS    | OS/2
  12874.  Flags: ENDUSER |
  12875.  Last Modified: 16-MAY-1989    ArticleIdent: Q40593
  12876.  
  12877.  It has been reported that when the keyword "default" is misspelled as
  12878.  "defualt", the C compiler does not generate an error and the
  12879.  executable code does not execute the "defualt" branch in any case.
  12880.  
  12881.  This is not a problem with the C compiler. When the keyword "default"
  12882.  is spelled incorrectly, it is treated as a label. You may use a goto
  12883.  statement to reference the label.
  12884.  
  12885.  Note: It is not a good programming practice to jump to a label that is
  12886.  within a switch statement from outside the switch statement.
  12887.  
  12888.  
  12889.  301. Accessing the COM3: or COM4: Port
  12890.  
  12891.  Product Version(s): 5.00 5.10
  12892.  Operating System:   MS-DOS
  12893.  Flags: ENDUSER |
  12894.  Last Modified: 16-MAY-1989    ArticleIdent: Q40594
  12895.  
  12896.  If the DOS, the ROM BIOS, and the hardware all support COM3: and COM4:
  12897.  as valid devices, then the DOS mode command may possibly be used to
  12898.  redirect communication to access the ports from within Microsoft C.
  12899.  For example, to redirect COM3: to COM1:, give the following command:
  12900.  
  12901.     mode COM3:=COM1:
  12902.  
  12903.  Note: This process has not been tested by Microsoft and is offered
  12904.  only as a suggestion.
  12905.  
  12906.  Versions of DOS earlier than MS-DOS Version 3.30 do not recognize the
  12907.  COM3: and COM4: ports. Versions beginning with MS-DOS Version 3.30
  12908.  allow some systems to access the ports, but the ROM BIOS also must
  12909.  support the extra communications port hardware.
  12910.  
  12911.  
  12912.  302. C memcpy and Large Model
  12913.  
  12914.  Product Version(s): 5.10
  12915.  Operating System:   MS-DOS
  12916.  Flags: ENDUSER | SR# G881031-5486
  12917.  Last Modified: 16-MAY-1989    ArticleIdent: Q40738
  12918.  
  12919.  Question:
  12920.  
  12921.  I normally compile a certain program with the /Ox switch. Inside a few
  12922.  modules, I use the #pragma function(memcpy) statement, to force the
  12923.  use of the function version of memcpy, which is required because I use
  12924.  memcpy with some huge pointers.
  12925.  
  12926.  This works correctly, until I want to use CodeView. At that time, I
  12927.  recompile with the switches /Od /Zi. This produces the following error
  12928.  message:
  12929.  
  12930.     Error C2164: 'memcpy': intrinsic was not declared
  12931.  
  12932.  Editing each module to remove the #pragma function(memcpy), which is
  12933.  not required in the /Od case, eliminates the error message. Editing
  12934.  the pragma in and out is a lot of work, however.
  12935.  
  12936.  Why is this required?
  12937.  
  12938.  Response:
  12939.  
  12940.  The C2164 error message is listed in ERRMSG.DOC, which is supplied
  12941.  with the compiler. (It's a good idea to print out all the .DOC files
  12942.  for reference; there's a lot of important information there that
  12943.  doesn't appear in the manuals.) When you don't use the -Oi or -Ox
  12944.  option, you need to declare a function prototype before you can use
  12945.  the function or intrinsic pragmas. An easy way to do this is to
  12946.  include the appropriate .H file: in this case, either STRING.H or
  12947.  MEMORY.H will do. This will work with or without intrinsics.
  12948.  
  12949.  
  12950.  303. How to Pass a Far Pointer from Parent to Spawned Child in C
  12951.  
  12952.  Product Version(s): 5.00 5.10
  12953.  Operating System:   MS-DOS
  12954.  Flags: ENDUSER | SR# G881208-7649
  12955.  Last Modified: 25-MAY-1989    ArticleIdent: Q40774
  12956.  
  12957.  Question:
  12958.  
  12959.  Is it possible to hand over a far pointer from a parent process to a
  12960.  child process? My parent process is doing a memory allocation that it
  12961.  fills with data. I'd like to be able to access this data in the child
  12962.  process.
  12963.  
  12964.  Response:
  12965.  
  12966.  The best way to pass a pointer to a child is to convert the pointer to
  12967.  an ASCII string using sprintf, spawn the child with the string on the
  12968.  command line, and convert the string back to a pointer with sscanf.
  12969.  Below is a sample program that does this. Note that the program and
  12970.  the child process must be compiled separately. Be sure to pass a far
  12971.  (segment and offset) pointer rather than a near (offset only)
  12972.  pointer. Attempting to pass a near pointer will not work.
  12973.  
  12974.  It is also possible to leave the pointer in an agreed-upon memory
  12975.  area. Frequently, unused interrupt vectors are used for this purpose.
  12976.  We do not recommend this method because it could cause conflicts with
  12977.  other software using the same memory. The method described above
  12978.  is much safer.
  12979.  
  12980.  A sample parent program and child program follow:
  12981.  
  12982.  /**************** parent process ****************/
  12983.  #include <process.h>
  12984.  #include <stdlib.h>
  12985.  #include <signal.h>
  12986.  #include <stdio.h>
  12987.  #include <string.h>
  12988.  
  12989.  char buffer[80];            /* buffer to be passed to child */
  12990.  char ascptr[20];            /* holds ASCII version of ptr.  */
  12991.  
  12992.  void main(void)
  12993.  {
  12994.  int ret;
  12995.  
  12996.                              /* initial string */
  12997.      strcpy(buffer, "Main1");
  12998.      printf("Beginning main1...\nString is:  %s\n", buffer);
  12999.  
  13000.                              /* convert address to ASCII */
  13001.      sprintf(ascptr, "%p", buffer);
  13002.      printf("ASCII version of pointer is: %p\nSpawning main2...\n\n",
  13003.              ascptr);
  13004.  
  13005.                              /* spawn, passing ASCII address on
  13006.                                 command line */
  13007.      ret = spawnlp(P_WAIT, "main2.exe", "main2", ascptr, NULL);
  13008.      printf("\nBack to main1--spawnlp returned %d\n", ret);
  13009.  
  13010.                              /* Show that string is changed */
  13011.      printf("String is now:  %s\nAll done", buffer);
  13012.      exit(0);
  13013.  }
  13014.  /* end of program number one*/
  13015.  
  13016.  /**************** child process--compile seperately! *************/
  13017.  #include <process.h>
  13018.  #include <stdlib.h>
  13019.  #include <signal.h>
  13020.  #include <stdio.h>
  13021.  #include <string.h>
  13022.  #include <ctype.h>
  13023.  
  13024.  char far *ptrstuff;
  13025.  
  13026.  void main(int argc, char **argv)
  13027.  {
  13028.  int ch;
  13029.  
  13030.      printf("In main2:  argv[1] is %s\n", argv[1]);
  13031.      if (argc != 2) {        /* error in argument list */
  13032.          printf("Error in argument list to main2\n");
  13033.          exit(1);
  13034.      }
  13035.  
  13036.                              /* retrieve pointer value from string */
  13037.      sscanf(argv[1], "%p", &ptrstuff);
  13038.      printf("\nPointer is actually set to:  %p\n", ptrstuff);
  13039.  
  13040.                              /* check to see that it's right */
  13041.      printf("Pointer points to: %s\n", ptrstuff);
  13042.  
  13043.                              /* change string (CAREFULLY!!!!!) */
  13044.      printf("Warning:  modifying the string incorrectly could hang "
  13045.             "your system...\n");
  13046.      printf("\007Should I modify this string? ");
  13047.      ch = getchar();
  13048.      if (toupper(ch) == 'Y')  {
  13049.          strcpy(ptrstuff, "2nd main");
  13050.          printf("Changed string to: %s\n", ptrstuff);
  13051.      }
  13052.      else printf("String not changed....\n");
  13053.  
  13054.      printf("Exiting main2...\n");
  13055.      exit(0);
  13056.  }
  13057.  /* end of child process */
  13058.  
  13059.  
  13060.  304. Using /ND to Put Uninitialized Data in a Named Segment
  13061.  
  13062.  Product Version(s): 5.10   | 5.10
  13063.  Operating System:   MS-DOS | OS/2
  13064.  Flags: ENDUSER |
  13065.  Last Modified: 16-MAY-1989    ArticleIdent: Q40777
  13066.  
  13067.  Question:
  13068.  
  13069.  When I compile the example below with the /NDsegname switch, why don't
  13070.  the variables a and b end up in the segname_BSS segment?
  13071.  
  13072.  #include <stdio.h>
  13073.  
  13074.  int a,b,c=2;
  13075.  
  13076.  main()
  13077.  {
  13078.  
  13079.  }
  13080.  
  13081.  How do I get my uninitialized global data and static data to go into
  13082.  the named data segment (namely segname_BSS)?
  13083.  
  13084.  Response:
  13085.  
  13086.  Variables that are declared outside of a function and not initialized
  13087.  are communal. The BTDATA_BSS segment is for uninitialized static data.
  13088.  So, when compiling with /ND:
  13089.  
  13090.  int a;      /* goes to FAR_BSS   */
  13091.  int b = 5;  /* goes to STUFF     */
  13092.  static c;   /* goes to STUFF_BSS */
  13093.  
  13094.  The reason that "int a;" is treated in this way is that it's legal to
  13095.  have such declarations in several modules as long as at most one of
  13096.  the declarations contains an initializer. The linker combines all
  13097.  these definitions into one. If it were subject to the /ND switch, the
  13098.  variable could be in different segments in different modules, which
  13099.  would be impossible to link.
  13100.  
  13101.  So, to put the variable in the STUFF group, either declare the
  13102.  variable static or initialize it (like either b or c above).
  13103.  
  13104.  
  13105.  305. Assembly Listing Doesn't Match Generated Code in C
  13106.  
  13107.  Product Version(s): 5.10   | 5.10
  13108.  Operating System:   MS-DOS | OS/2
  13109.  Flags: ENDUSER |
  13110.  Last Modified: 25-MAY-1989    ArticleIdent: Q40783
  13111.  
  13112.  Microsoft has received several reports that the listings generated by
  13113.  the /Fc, /Fl, and /Fa options do not match the actual code in the
  13114.  .OBJ or .EXE file, as viewed by CodeView.
  13115.  
  13116.  In these cases, we have found that the file has been compiled using
  13117.  different options when creating the listing than when producing the
  13118.  CodeView file. In particular, adding the /Zi option causes some
  13119.  changes in the generated code. As we document, /Zi turns off
  13120.  optimizations that move code.
  13121.  
  13122.  If the listing was generated without /Zi, but the .EXE being viewed in
  13123.  CodeView was compiled with /Zi, there often are differences between
  13124.  the CodeView listing and the printed listing.
  13125.  
  13126.  Be sure to use EXACTLY the same options when comparing listing files
  13127.  with the actual code.
  13128.  
  13129.  
  13130.  306. Available Memory in C with More Than 20 Files and PC-DOS 3.30
  13131.  
  13132.  Product Version(s): 5.10
  13133.  Operating System:   MS-DOS
  13134.  Flags: ENDUSER |
  13135.  Last Modified: 16-MAY-1989    ArticleIdent: Q40785
  13136.  
  13137.  Question:
  13138.  
  13139.  Following the directions in the C 5.10 README.DOC file, I have
  13140.  modified the CRT0DAT.ASM file to increase the number of file handles
  13141.  from 20 to 30. I have a simple program (below) that checks the amount
  13142.  of available memory. When I link it with the modified CRT0DAT and
  13143.  execute the program, the amount of available memory is significantly
  13144.  less (approximately 64K) if I am running PC-DOS 3.30 than it is if I
  13145.  am running MS-DOS 3.30.
  13146.  
  13147.  Note: If I do not link in the CRT0DAT, then the difference in the
  13148.  available memory between MS-DOS 3.30 and PC-DOS 3.30 is negligible.
  13149.  
  13150.  All memory models will produce results similar to those described
  13151.  above.
  13152.  
  13153.  How can I eliminate this inconsistency between the two versions of
  13154.  DOS?
  13155.  
  13156.  Response:
  13157.  
  13158.  The only workarounds are to not link with a modified CRT0DAT.ASM, or
  13159.  to use MS-DOS instead of PC-DOS.
  13160.  
  13161.  Microsoft is researching this problem and will post more information
  13162.  as it becomes available.
  13163.  
  13164.  The following program, compiled with "cl /W3 /c", demonstrates the
  13165.  problem:
  13166.  
  13167.  #include <stdio.h>
  13168.  #include <dos.h>
  13169.  
  13170.  void main(void)
  13171.  {
  13172.     unsigned size;
  13173.     unsigned segment;
  13174.  
  13175.     printf("Checking memory:\n");
  13176.     size = 0xffff;
  13177.     if (_dos_allocmem (size, &segment))
  13178.        printf("Available paragraphs: %u\n",segment);
  13179.     else
  13180.        printf("Memory allocated.\n");
  13181.  }
  13182.  
  13183.  
  13184.  307. C Compiler Error: (compiler file '@(#)code.c1.46, line 393)
  13185.  
  13186.  Product Version(s): 5.10   | 5.10
  13187.  Operating System:   MS-DOS | OS/2
  13188.  Flags: ENDUSER |
  13189.  Last Modified: 16-MAY-1989    ArticleIdent: Q40786
  13190.  
  13191.  The code below generates the following error when compiled with any
  13192.  /A?f? option:
  13193.  
  13194.     fatal error C1001 Internal Compiler Error
  13195.     (compiler file '@(#)code.c1.46, line 393)
  13196.  
  13197.  To work around the problem, use a different memory model, use only one
  13198.  register variable, or simplify the assignment with temporary
  13199.  variables.
  13200.  
  13201.  Sample code that demonstrates the problem follows:
  13202.  
  13203.  int main()
  13204.  {
  13205.      char *buff;
  13206.      char *ptr[8];
  13207.  
  13208.      register int k;
  13209.      register int i;
  13210.  
  13211.      *ptr[i]++ = buff[k++];
  13212.  }
  13213.  
  13214.  
  13215.  308. _edata and _end Are Defined by LINK
  13216.  
  13217.  Product Version(s): 5.10   | 5.10
  13218.  Operating System:   MS-DOS | OS/2
  13219.  Flags: ENDUSER | S_LINK
  13220.  Last Modified: 16-MAY-1989    ArticleIdent: Q40810
  13221.  
  13222.  Question :
  13223.  
  13224.  In the map file generated by Microsoft LINK, there are two symbols:
  13225.  _edata and _end. What are they?
  13226.  
  13227.  Response:
  13228.  
  13229.  When the /DOSSEG (default) option is used with the LINK command, these
  13230.  two symbols are created by LINK and are used in the C startup code as
  13231.  markers. They are only meaningful for the Microsoft C and FORTRAN
  13232.  Compilers.
  13233.  
  13234.  This information is explained on Page 273 of the "Microsoft CodeView
  13235.  and Utilities Software Development Tools for the MS-DOS Operating
  13236.  System" manual for C Version 5.00 or 5.10 in the LINK section. The
  13237.  note on this page states that the _edata points to the beginning of
  13238.  the BSS segment; _end points to the end of the BSS segment and the
  13239.  beginning of the STACK segment.
  13240.  
  13241.  These two symbols can be found in the startup source code file
  13242.  CRT0.ASM. The startup source code is included in the Microsoft C
  13243.  Optimizing Compiler for Versions 5.00 and 5.10.
  13244.  
  13245.  
  13246.  309. Maximum Number of Include Directories Is 15
  13247.  
  13248.  Product Version(s): 5.00 5.10  | 5.10
  13249.  Operating System:   MS-DOS     | OS/2
  13250.  Flags: ENDUSER | limits
  13251.  Last Modified: 31-JAN-1989    ArticleIdent: Q40837
  13252.  
  13253.  There is a maximum number of directories you can set in both the
  13254.  compile line and the INCLUDE environment variable. The combined
  13255.  maximum is 15. Exceeding the maximum can cause the error U1013 or
  13256.  U1077 in a MAKE file.
  13257.  
  13258.  No error message is given if the compile line is typed in directly
  13259.  from the DOS prompt. The program just fails to compile. This maximum
  13260.  applies to both DOS and OS/2.
  13261.  
  13262.  Note: If you have 14 directories in your include environment variable
  13263.  and added several others at the command line (with one /I, as opposed
  13264.  to using a /I for every directory), you could break this boundary.
  13265.  However, you should normally avoid using more than 15 directories.
  13266.  
  13267.  
  13268.  310. FATAL: Internal Stack Failure, System Halted
  13269.  
  13270.  Product Version(s): 5.00 5.10
  13271.  Operating System:   MS-DOS
  13272.  Flags: ENDUSER | S_QUICKC S_PASCAL H_FORTRAN H_MASM
  13273.  Last Modified: 16-MAY-1989    ArticleIdent: Q41024
  13274.  
  13275.  For DOS Version 3.20 or later, the following message is issued by DOS
  13276.  when too many interrupts occur too quickly and the pool of internal
  13277.  stack frames is exhausted:
  13278.  
  13279.     FATAL: Internal Stack Failure, System Halted
  13280.  
  13281.  Increasing the number of stacks allocated for use by interrupt
  13282.  handlers in the STACKS command in CONFIG.SYS usually corrects the
  13283.  problem.
  13284.  
  13285.  The syntax is as follows:
  13286.  
  13287.  STACKS=n,s
  13288.  
  13289.  n = number of stacks, ranging from 8 to 64, with 9 as the as the default
  13290.  s = size of each stack, ranging from 32 to 512 bytes, default of 128
  13291.  
  13292.  For more information about the STACKS command, see Page 805 of the
  13293.  "MS-DOS Encyclopedia."
  13294.  
  13295.  This error can occur if network cards, laboratory measurement
  13296.  instruments, and other devices are in use. They may generate many
  13297.  hardware interrupts thus exhausting the DOS stack resources.
  13298.  
  13299.  Note: For MS-DOS Version 3.30 on an IBM-PC, IBM-XT, or
  13300.  IBM-PC-Portable, the default for n is 0 and s is 0 .
  13301.  
  13302.  
  13303.  
  13304.  311. Libraries Added by the Comment pragma Appear After Default
  13305.  
  13306.  Product Version(s): 5.10   | 5.10
  13307.  Operating System:   MS-DOS | OS/2
  13308.  Flags: ENDUSER | docerr
  13309.  Last Modified: 11-SEP-1989    ArticleIdent: Q41104
  13310.  
  13311.  Page 12 of the "Microsoft C for MS OS/2 and MS-DOS Operating Systems:
  13312.  Version 5.1 Update" manual states that when using the library option
  13313.  of the comment pragma, the specified library name will be inserted
  13314.  before the default library name in the object module. This is not the
  13315.  case; the given library name appears after the default library name.
  13316.  This agrees with the next statement in the documentation that states
  13317.  that using this pragma is the same as giving the library to LINK on
  13318.  the command line.
  13319.  
  13320.  If the order of the default library and an added library is important,
  13321.  compiling with the /Zl switch will prevent the default library name
  13322.  from being placed in the object module. A second comment pragma then
  13323.  can be used to insert the name of the default library after the added
  13324.  library. The libraries listed with these pragmas will appear in the
  13325.  object module in the same order they are found in the source code.
  13326.  
  13327.  
  13328.  312. C Versions 3.00, 4.00 Do Not Require Semicolon in Structure
  13329.  
  13330.  Product Version(s): 3.00 4.00 5.00 5.10
  13331.  Operating System:   MS-DOS
  13332.  Flags: ENDUSER |
  13333.  Last Modified: 16-MAY-1989    ArticleIdent: Q41158
  13334.  
  13335.  Microsoft C Versions 3.00 and 4.00 do not require a semicolon to be
  13336.  put after each field in the structure declaration. The following piece
  13337.  of code does not produce any errors in C Versions 3.00 and 4.00:
  13338.  
  13339.  struct one
  13340.  {
  13341.     int i
  13342.  };
  13343.  
  13344.  Microsoft C Versions 5.00 and 5.10 do require a semicolon after each
  13345.  field and will generate the following error if the semicolon
  13346.  is not there:
  13347.  
  13348.  error C2143
  13349.  syntax error: missing ';' before '}'
  13350.  
  13351.  Note: According to the Kernighan and Ritchie, semicolons are required
  13352.  after each field in the structure declaration.
  13353.  
  13354.  
  13355.  313. rewind(stdin) Clears Keyboard Buffer
  13356.  
  13357.  Product Version(s): 5.00 5.10 | 5.10
  13358.  Operating System:   MS-DOS    | OS/2
  13359.  Flags: ENDUSER | s_quickc
  13360.  Last Modified: 16-MAY-1989    ArticleIdent: Q41159
  13361.  
  13362.  Problem:
  13363.  
  13364.  I am trying to clear the keyboard buffer. It seems that using the
  13365.  function "fflush" on stream "stdin" does not have any effect.
  13366.  
  13367.  Response :
  13368.  
  13369.  The function "fflush" clears the buffers that C programs use for
  13370.  stream level I/O. It doesn't clear the device buffer.
  13371.  
  13372.  To clear the keyboard buffer, use the function "rewind" with the
  13373.  stream "stdin", which is associated with the keyboard by default.
  13374.  The function is prototyped in "stdio.h".
  13375.  
  13376.  The following is an example to demonstrate the usage:
  13377.  
  13378.  #include <stdio.h>
  13379.  void main(void)
  13380.  {
  13381.  int ch ;
  13382.  
  13383.  ch = getchar() ;    /* input more than one character
  13384.                      ** to see the effect of rewind(stdin) */
  13385.  putchar(ch) ;
  13386.  putchar('\n') ;
  13387.  
  13388.  rewind(stdin) ;
  13389.  ch = getchar() ;    /* will wait for new input even the first input
  13390.                      ** has more than one character */
  13391.  putchar(ch) ;
  13392.  }
  13393.  
  13394.  
  13395.  314. Getpid under DOS Is Not Functional
  13396.  
  13397.  Product Version(s): 5.00 5.10
  13398.  Operating System:   MS-DOS
  13399.  Flags: ENDUSER |
  13400.  Last Modified: 16-MAY-1989    ArticleIdent: Q41160
  13401.  
  13402.  Under DOS versions earlier than Version 4.00, the getpid() function
  13403.  returns the current time rather then the process ID as expected.
  13404.  
  13405.  DOS is a single-tasking operating system, so it does not generate a
  13406.  process ID and the Getpid function should not be used. Getpid is
  13407.  intended to be used with OS/2 and serves no purpose under DOS.
  13408.  
  13409.  
  13410.  315. How ungetch() Works with getch() and getche()
  13411.  
  13412.  Product Version(s): 5.00 5.10 | 5.10
  13413.  Operating System:   MS-DOS    | OS/2
  13414.  Flags: ENDUSER | s_quickc
  13415.  Last Modified: 16-MAY-1989    ArticleIdent: Q41198
  13416.  
  13417.  The Microsoft C run-time function ungetch() pushes back a character
  13418.  to be read in by the next call to getch() or getche().
  13419.  
  13420.  The character is pushed back to a special memory buffer defined in
  13421.  getch(). The function getch() or getche() checks the special buffer
  13422.  before it calls the DOS interrupt function to read input from the real
  13423.  keyboard buffer. If the special buffer is not empty, it returns the
  13424.  value in the buffer without calling the interrupt 21h function.
  13425.  
  13426.  ungetch() does not put the character back to the keyboard buffer.
  13427.  
  13428.  Pushing a character back to the keyboard buffer can be done on some
  13429.  machines by calling BIOS keyboard service, interrupt 16H function 05H
  13430.  with scan code in the register CH and the character's ASCII code in
  13431.  the register CL.
  13432.  
  13433.  Note: This BIOS function does not exist on many machines -- be sure to
  13434.  check the machine you're running on before you try to use this
  13435.  function.
  13436.  
  13437.  
  13438.  316. getch() Misbehaves on Keyboard Inputs ALT+Q, ALT+R
  13439.  
  13440.  Product Version(s): 5.10
  13441.  Operating System:   MS-DOS
  13442.  Flags: ENDUSER |
  13443.  Last Modified: 16-MAY-1989    ArticleIdent: Q41203
  13444.  
  13445.  Problem:
  13446.  
  13447.  The sample program below accepts all the keyboard inputs normally,
  13448.  including most of the ALT combination keys. But it appears to behave
  13449.  incorrectly on two keyboard inputs: ALT+Q and ALT+R.
  13450.  
  13451.  Response:
  13452.  
  13453.  This is not a problem with the Microsoft C Optimizing Compiler
  13454.  run-time function getch(). The problem is caused because DOS uses the
  13455.  values of these two ALT combination keys for other control purposes.
  13456.  
  13457.  In this case, the second scancode of ALT+Q is 16 and the second
  13458.  scancode of ALT+R is 19 (both decimal). DOS uses scancode 16 to mean
  13459.  "echo subsequent output to the printer" and scancode 19 to mean "pause
  13460.  output." These are equivalent to CTRL+P and CTRL+S. When a printer is
  13461.  not connected to the computer, the PRINT SCREEN key has to wait for
  13462.  time out. For the SCREEN PAUSE key, another key has to be pressed to
  13463.  activate the screen again.
  13464.  
  13465.  We recommend using the _bios_keybrd() function rather than getch()
  13466.  when you might press ALT+R or ALT+Q.
  13467.  
  13468.  Usually the ALT combination keys generate 2 bytes in the keyboard
  13469.  buffer. The program below checks if the first byte is zero. If it is
  13470.  zero the program reads in the next byte, which has the value for that
  13471.  particular ALT combination key.
  13472.  
  13473.  The following is a code example:
  13474.  
  13475.  /* sample program */
  13476.  #include <stdio.h>
  13477.  #include <conio.h>
  13478.  void main(void)
  13479.  {
  13480.      int ch, scan;
  13481.  
  13482.      do {
  13483.          ch = getch();    /* 1st getch() gets ASCII code */
  13484.          printf("Character is %d\n", ch);
  13485.          if (ch == 0) {    /* if ASCII code was zero */
  13486.              scan = getch();  /* 2nd getch() gets "scan code" */
  13487.              printf("\tExtended character:  scan is %d\n", scan);
  13488.          }
  13489.      }  while (ch != 27);    /* exit loop on ESC */
  13490.  }
  13491.  
  13492.  To read the combination keys successfully, use the function
  13493.  _bios_keybrd(). The following is an example that works in a similar
  13494.  manner to the example above. Note: Because _bios_keybrd() returns
  13495.  both the scan code and the ASCII value in the high and low bytes of
  13496.  the return value, only one call to _bios_keybrd() is necessary for
  13497.  each keystroke.
  13498.  
  13499.  The following is a code example:
  13500.  
  13501.  #include <stdio.h>
  13502.  #include <bios.h>
  13503.  
  13504.  void main(void)
  13505.  {
  13506.  unsigned scan_asc;
  13507.  int ch, scan;
  13508.  
  13509.      do {
  13510.          scan_asc = _bios_keybrd(_KEYBRD_READ);
  13511.          ch = scan_asc & 0xff;  /* character in low byte */
  13512.          scan = scan_asc >> 8;   /* scan code in high byte */
  13513.          printf("Character is %d\n", ch) ;
  13514.          if (ch == 0) {
  13515.              printf("\tExtended character:  scan is %d\n", scan) ;
  13516.          }
  13517.      }  while (ch != 27) ;   /* exit loop on ESC key */
  13518.  }
  13519.  
  13520.  
  13521.  317. Prototypes Must Be Used Before Intrinsic or Function Pragmas
  13522.  
  13523.  Product Version(s): 5.10   | 5.10
  13524.  Operating System:   MS-DOS | OS/2
  13525.  Flags: ENDUSER | SR# G881031-5486
  13526.  Last Modified: 16-MAY-1989    ArticleIdent: Q41212
  13527.  
  13528.  Question:
  13529.  
  13530.  I normally compile a certain program with the /Ox switch. Inside a few
  13531.  modules, I use the #pragma function(memcpy) statement to force the
  13532.  use of the function version of memcpy, which is required because I use
  13533.  memcpy with some "huge" pointers.
  13534.  
  13535.  This works correctly until I want to use CodeView. At that time, I
  13536.  recompile with the switches /Od /Zi. This produces the following error
  13537.  message:
  13538.  
  13539.     Error C2164: 'memcpy': intrinsic was not declared.
  13540.  
  13541.  Editing each module to remove the #pragma function(memcpy), which is
  13542.  not required in the /Od case, eliminates the error message. However
  13543.  this is time consuming. Why is this required?
  13544.  
  13545.  Note: Error C2164 is not listed in the "Microsoft C for MS-DOS
  13546.  Operating System: User's Guide."
  13547.  
  13548.  Response:
  13549.  
  13550.  When you don't use the -Oi or -Ox option, you need to declare a
  13551.  function prototype before you can use the function or intrinsic
  13552.  pragmas. One method is to include the appropriate .h file -- for this
  13553.  function, either string.h or memory.h will work correctly.
  13554.  
  13555.  The C2164 error message is listed in errmsg.doc, which is supplied
  13556.  with the compiler. (It's a good idea to print out all the .doc files
  13557.  for reference; there's a lot of important information there that
  13558.  doesn't appear in the manuals.)
  13559.  
  13560.  
  13561.  318. How to Trap CTRL+C
  13562.  
  13563.  Product Version(s): 5.10
  13564.  Operating System:   MS-DOS
  13565.  Flags: ENDUSER | appnote softlib CTRLC.ARC S12319.EXE
  13566.  Last Modified: 25-JUL-1989    ArticleIdent: Q45497
  13567.  
  13568.  An application note is available that demonstrates how to trap the
  13569.  CTRL+C and CTRL+BREAK key combinations. This application note is
  13570.  available from Microsoft Product Support Services by calling (206)
  13571.  454-2030. This application note is also available from the Microsoft
  13572.  PSS System Languages group.
  13573.  
  13574.  This information is also available in the Software/Data library by
  13575.  searching on the keyword CTRLC, the Q number of this article, or
  13576.  S12319. CTRLC was archived using the PKware file-compression utility.
  13577.  
  13578.  The file provided is fully tested; however, it is not regularly
  13579.  released with the Microsoft C Version 5.10 Compiler. Consequently, it
  13580.  will not be maintained and any problem reported against it will not
  13581.  result in a patch or any other immediate repair. Problems experienced
  13582.  with this file should be reported to Microsoft Product Support
  13583.  Services.
  13584.  
  13585.  CTRLC contains the following files:
  13586.  
  13587.     README.NOW - Brief description of program and Microsoft
  13588.     disclaimer
  13589.  
  13590.     CTRL.C - Code example for trapping the CTRL+C and CTRL+BREAK
  13591.     key combinations
  13592.  
  13593.  
  13594.  319. Alleged Problems with Listing Options (/Fc, /Fl, /Fa)
  13595.  
  13596.  Product Version(s): 5.10   | 5.10
  13597.  Operating System:   MS-DOS | OS/2
  13598.  Flags: ENDUSER | SR# S881208-32 errors
  13599.  Last Modified: 25-MAY-1989    ArticleIdent: Q41217
  13600.  
  13601.  Microsoft has received reports that the assembly listing options (/Fc,
  13602.  /Fl, /Fa) produce listings that don't accurately reflect the code
  13603.  generated.
  13604.  
  13605.  We have determined that this problem is caused
  13606.  because different compiler options are being used when compiling to
  13607.  produce the listing, than when compiling to produce an executable. An
  13608.  especially common situation is to use /Zi for compiling the executable
  13609.  and to leave it off when compiling to produce a listing.
  13610.  
  13611.  The /Zi option DOES in fact cause slightly different code to be
  13612.  generated because optimizations that would move code are  suppressed.
  13613.  Therefore, it is perfectly normal for the CodeView listing of a
  13614.  program compiled with /Zi to differ somewhat from the listing produced
  13615.  when compiled without /Zi.
  13616.  
  13617.  If you find a case in which the listing is different from the
  13618.  generated code when both are compiled with EXACTLY the same options,
  13619.  please report the problem to Microsoft.
  13620.  
  13621.  
  13622.  320. Program Hangs the Second Time It Is Run Using an 80287
  13623.  
  13624.  Product Version(s): 5.00 5.10
  13625.  Operating System:   MS-DOS
  13626.  Flags: ENDUSER |
  13627.  Last Modified: 16-MAY-1989    ArticleIdent: Q41220
  13628.  
  13629.  When compiling a program that uses signal() with an 80287 coprocessor,
  13630.  the first time the program runs, everything works correctly. But if
  13631.  run a second time, it hangs the computer.
  13632.  
  13633.  This problem has been confirmed to be with the old 80287 coprocessors
  13634.  and has been corrected in newer 80287 chips.
  13635.  
  13636.  The example program in the "Microsoft C for the MS-DOS Operating
  13637.  System: Run-Time Library Reference" manual on Page 280 locks up on the
  13638.  second time the program is executed with an old 80287. The following
  13639.  is an example:
  13640.  
  13641.  #include <stdio.h>
  13642.  #include <signal.h>
  13643.  #include <setjmp.h>
  13644.  #include <float.h>
  13645.  
  13646.  int fphandler ();
  13647.  jmp_buf mark;
  13648.  double a = 1.0, b = 0.0, c;
  13649.  
  13650.  main()
  13651.  {
  13652.      if(signal(SIGFPE, fphandler) == (int(*) () ) -1)
  13653.       abort();
  13654.  
  13655.      if(setjmp(mark) == 0)
  13656.      {
  13657.       c = a/b;
  13658.       printf("Should never get here\n");
  13659.      }
  13660.  
  13661.      printf("Recovered from floating-point error\n");
  13662.  }
  13663.  
  13664.  int fphandler (sig, num)
  13665.  int sig, num;
  13666.  {
  13667.      printf("signal = %d subcode = %d\n", sig, num);
  13668.      _fpreset();
  13669.      longjmp(mark, -1);
  13670.  }
  13671.  
  13672.  
  13673.  321. Use Huge Pointers If Object Is Larger Than 64K Boundary
  13674.  
  13675.  Product Version(s): 5.10
  13676.  Operating System:   OS/2
  13677.  Flags: ENDUSER | SR# G890201-11081
  13678.  Last Modified: 16-MAY-1989    ArticleIdent: Q41247
  13679.  
  13680.  Question:
  13681.  
  13682.  I'm declaring a pointer that points into an array by saying the
  13683.  following:
  13684.  
  13685.    char huge carray[70000];
  13686.    char *pchar = carray;
  13687.  
  13688.  I compile the program using large-memory model.
  13689.  
  13690.  When I access the array using carray, everything work correctly.
  13691.  However, when I use the pointer pchar, I can't seem to access the
  13692.  array past the 64K boundary. What's wrong?
  13693.  
  13694.  Response:
  13695.  
  13696.  The problem is caused by using a far pointer in a situation where you
  13697.  need a huge pointer.
  13698.  
  13699.  There are three types of data pointers in Microsoft C: near, far, and
  13700.  huge. Near pointers represent offsets within DGROUP (the default data
  13701.  segment) and are stored in 2 bytes. Far and huge pointers contain both
  13702.  a segment address/selector and an offset and therefore take 4 bytes.
  13703.  
  13704.  Although far and huge pointers are identical in format, the algorithms
  13705.  used to do addressing calculations involving these two types of
  13706.  pointers are very different. Far pointers are assumed to point to a
  13707.  data item that does not cross a segment boundary (in other words, the
  13708.  size of the item must be less than 64K). As a result, the compiler
  13709.  ignores the segment part of the pointer in all calculations except for
  13710.  "equals" and "not equals" tests. This gives a considerable (more than
  13711.  2 times) savings in execution time for these operations. In fact,
  13712.  calculations involving far pointers are almost as fast as calculations
  13713.  involving near pointers.
  13714.  
  13715.  Huge pointers may point to items that are larger than 64K. The
  13716.  addressing arithmetic work on both the segment and the offset, if
  13717.  necessary. Huge pointer arithmetic is therefore considerably slower
  13718.  than far arithmetic, but it has the advantage of working when the data
  13719.  item is larger than 64K.
  13720.  
  13721.  Your code should work correctly if you declare pchar to be a huge
  13722.  pointer rather than a far (default for large-memory model) pointer. If
  13723.  you didn't want to add the huge keyword to the declaration, you could
  13724.  compile with the /AH option. It is recommended to use the huge keyword
  13725.  rather than /AH because it allows you to control when huge arithmetic
  13726.  is performed -- if you use /AH, then ALL pointers are huge.
  13727.  
  13728.  
  13729.  322. Number of Serial Ports under OS/2
  13730.  
  13731.  Product Version(s): 5.10
  13732.  Operating System:   OS/2
  13733.  Flags: ENDUSER | SR# G890121-10245
  13734.  Last Modified: 16-MAY-1989    ArticleIdent: Q41255
  13735.  
  13736.  The number of serial ports that can be supported under OS/2 is
  13737.  dependent on how your OS/2 vendor set up the device drivers
  13738.  shipped with the operating system. Most are set up with two ports for
  13739.  AT-type machines and three for PS/2 type machines. Each vendor writes
  13740.  its own communications device drivers, so it really depends on what
  13741.  the vendor is doing.
  13742.  
  13743.  Note: Both original and third-party vendors can support additional
  13744.  ports (essentially, as many as they like) if they write or modify
  13745.  device drivers to do so.
  13746.  
  13747.  
  13748.  323. ROMable Code Using Microsoft C
  13749.  
  13750.  Product Version(s): 5.10
  13751.  Operating System:   MS-DOS
  13752.  Flags: ENDUSER | SR# G890121-10245 appnote
  13753.  Last Modified: 31-MAY-1989    ArticleIdent: Q41256
  13754.  
  13755.  Question:
  13756.  
  13757.  How can I use the Microsoft C Compiler to produce code that will be
  13758.  put into ROM?
  13759.  
  13760.  Response:
  13761.  
  13762.  The best way is to use a third-party package designed to produce
  13763.  ROMable code using Microsoft C. The linker supplied with our compiler
  13764.  only produces code designed to run under the DOS and OS/2
  13765.  environments. CodeView only runs under DOS or OS/2. Third-party
  13766.  packages typically include an alternate linker and debugger.
  13767.  
  13768.  You can find out more about these third-party packages by obtaining a
  13769.  copy of a technically oriented PC magazine or by talking with a dealer
  13770.  who sells such packages. Microsoft also provides an application note
  13771.  called "Writing ROMable Code in Microsoft C," which can be obtained
  13772.  from Microsoft Product Support Services by calling (206) 454-2030.
  13773.  
  13774.  
  13775.  324. What Is the Format of an .EXE File?
  13776.  
  13777.  Product Version(s): 5.10
  13778.  Operating System:   MS-DOS
  13779.  Flags: ENDUSER | SR# G890118-9899
  13780.  Last Modified: 16-MAY-1989    ArticleIdent: Q41257
  13781.  
  13782.  Question:
  13783.  
  13784.  What is the format of an .EXE file?
  13785.  
  13786.  Response:
  13787.  
  13788.  The .EXE file format is documented in a number of places, including
  13789.  the "MS-DOS Programmer's Reference." Probably the best documentation
  13790.  you'll find is in the MS-DOS Encyclopedia, starting on Page 119. There
  13791.  is also an appendix on the new segmented format used by Windows in the
  13792.  back of this reference.
  13793.  
  13794.  The MS-DOS Encyclopedia is an incredibly valuable reference for
  13795.  systems programmers. The format is too long and complicated to
  13796.  reproduce here.
  13797.  
  13798.  
  13799.  325. Calculating Available Memory in Large Model
  13800.  
  13801.  Product Version(s): 5.10
  13802.  Operating System:   MS-DOS
  13803.  Flags: ENDUSER | SR# G890215-12018
  13804.  Last Modified: 16-MAY-1989    ArticleIdent: Q41345
  13805.  
  13806.  Question:
  13807.  
  13808.  I am using large-memory model (C Version 5.10). My program makes a
  13809.  call to the _memavl() function to see how much memory is remaining. I
  13810.  get back some number (e.g. 29320 bytes). Then I malloc some buffers
  13811.  for linked lists, data structures and place another call to _memavl. I
  13812.  get the same number back.
  13813.  
  13814.  Shouldn't the number get smaller after I have malloc'd memory?
  13815.  
  13816.  Is there a way for me to find out how much free memory (total) is
  13817.  available?
  13818.  
  13819.  Response:
  13820.  
  13821.  There are actually two memory-allocation heaps when you're using large
  13822.  model. The near heap is the unused portion of the 64K DGROUP segment.
  13823.  The far heap is the unused memory above your program. malloc() uses
  13824.  the near heap for small and medium models and the far heap for
  13825.  compact, large, and huge models. (You can choose which heap to use by
  13826.  using _fmalloc() for the far heap and _nmalloc() for the near heap.)
  13827.  
  13828.  The _memavl() function only measures the amount of memory available
  13829.  on the near heap. Because the near heap is not used in far model until
  13830.  the far heap is exhausted, _memavl() shouldn't change.
  13831.  
  13832.  To measure the amount of memory available on the far heap, you can
  13833.  use the _dos_allocmem() function. (This function calls the DOS
  13834.  memory-allocation function.) Pass the function 0xFFFF for the number
  13835.  of 16-byte paragraphs to allocate (which is 1 megabyte more memory
  13836.  than the machine has) and the address of an unsigned int. When the
  13837.  function returns, the unsigned int whose address you passed will
  13838.  contain the paragraph size of the largest contiguous block in the far
  13839.  heap. To find the number of bytes, multiply this by the 16L, which is
  13840.  the size of a paragraph. (Use 16L rather than 16 so that the
  13841.  multiplication will be done using long math, avoiding possible
  13842.  overflow.)
  13843.  
  13844.  The total memory available is the sum of the amount available on the
  13845.  far and near heaps. For best accuracy, you should do this calculation
  13846.  immediately after your program begins.
  13847.  
  13848.  There are a few traits of the malloc() allocation you should be aware
  13849.  of, as follows:
  13850.  
  13851.  1. malloc() does NOT call DOS for each small allocation. Instead, it
  13852.     asks DOS for an 8K block (this size can be set by setting the
  13853.     global variable _amblksiz, as described on Page 33 of the
  13854.     "Microsoft C Run-Time Library Reference"), then allocates from this
  13855.     block. If the requested allocation is more than than 8K, malloc
  13856.     allocates enough 8K blocks to fulfill the allocation. Before
  13857.     malloc() asks DOS for memory, it first tries to allocate the
  13858.     request from memory it already has.
  13859.  
  13860.  2. free() NEVER returns memory to DOS. So, if you allocated a block,
  13861.     checked the far heap space using _dos_allocmem(), free()'d the
  13862.     block and checked again, the amount of memory available to DOS
  13863.     would NOT increase on the second call. You can get a better idea of
  13864.     how much memory is available by using _fheapwalk() to find out how
  13865.     much memory is available to malloc() but not to DOS.
  13866.  
  13867.  Note: halloc() calls DOS directly and frees directly to DOS.
  13868.  
  13869.  A program that calculates an estimate of the total amount of free
  13870.  memory follows:
  13871.  
  13872.  #include <malloc.h>
  13873.  #include <dos.h>
  13874.  #include <stdio.h>
  13875.  
  13876.  void main(void)
  13877.  {
  13878.  long totalavail;
  13879.  unsigned farparaavail;
  13880.  
  13881.      _dos_allocmem(0xFFFF, &farparaavail);
  13882.  
  13883.      totalavail = (long)farparaavail * 16L + _memavl();
  13884.  
  13885.      printf("Total memory available is about %ld bytes\n", totalavail);
  13886.  
  13887.  }
  13888.  
  13889.  
  13890.  326. Run-Time Library Reference vfprintf Documentation Error
  13891.  
  13892.  Product Version(s): 5.00 5.10 | 5.10
  13893.  Operating System:   MS-DOS    | OS/2
  13894.  Flags: ENDUSER | docerr s_quickc
  13895.  Last Modified: 16-MAY-1989    ArticleIdent: Q41369
  13896.  
  13897.  Page 636 of the "Microsoft C 5.10 Optimizing Compiler Run-Time Library
  13898.  Reference" and the "Microsoft QuickC Run-Time Library Reference"
  13899.  contains an error. In the example listed, the line
  13900.  
  13901.     error("Error: line %d, file  filename);
  13902.  
  13903.  should read
  13904.  
  13905.     error("Error: line %d, file %s\n", line, filename);
  13906.  
  13907.  
  13908.  327. _Setvideomode _ERESCOLOR Only Supports 16 Colors
  13909.  
  13910.  Product Version(s): 5.10
  13911.  Operating System:   MS-DOS
  13912.  Flags: ENDUSER | s_quickc docerr langdoc
  13913.  Last Modified: 16-MAY-1989    ArticleIdent: Q41373
  13914.  
  13915.  The manifest constant _ERESCOLOR is incorrectly shown as providing 64
  13916.  colors on Page 539 of the "Microsoft C Optimizing Compiler Version
  13917.  5.10 Run-Time Library Reference" manual, Page 539 of the "Microsoft
  13918.  QuickC Run-time Library Reference" manual, and Page 197 of the
  13919.  "Microsoft QuickC Version 2.00 Graphics Library Reference" manual.
  13920.  According to the "Programmer's Guide to PC & PS/2 Video Systems," Page
  13921.  448, and the "MS-DOS Encyclopedia," Page 1513, the correct number of
  13922.  colors in 640 x 350 EGA is 16 colors. The include file graph.h
  13923.  correctly shows 16 colors.
  13924.  
  13925.  
  13926.  328. Assignment of Void Pointer Does Not Give Warning Message
  13927.  
  13928.  Product Version(s): 5.10 | 5.00 5.10
  13929.  Operating System:   OS/2 | MS-DOS
  13930.  Flags: ENDUSER | s_quickc
  13931.  Last Modified: 16-MAY-1989    ArticleIdent: Q41374
  13932.  
  13933.  The code below shows an inconsistency with the way that the Microsoft
  13934.  C and QuickC compilers deal with pointer checking. The ANSI Standard
  13935.  is unclear as to whether an assignment to a void pointer should be
  13936.  checked to see if it is being assigned a nonpointer variable. The code
  13937.  below shows that character pointers are checked while void pointers
  13938.  are not; the code will generate a warning message at the default
  13939.  warning level:
  13940.  
  13941.  Warning C4017 : '=' different levels of indirection
  13942.  
  13943.  int i;         /* includes float,double,char,long,unsigned */
  13944.  char * p;
  13945.  void * v;
  13946.  
  13947.  main() {
  13948.      p = i;    /* this will give a warning message */
  13949.      v = i;    /* this will not give a warning message */
  13950.      }
  13951.  
  13952.  
  13953.  329. Documentation Error Page 136 _bios_equiplist
  13954.  
  13955.  Product Version(s): 5.10   | 5.10
  13956.  Operating System:   MS-DOS | OS/2
  13957.  Flags: ENDUSER | s_quickc docerr
  13958.  Last Modified: 16-MAY-1989    ArticleIdent: Q41441
  13959.  
  13960.  Page 136 of the "Microsoft C 5.10 Run-Time Library Reference" manual
  13961.  incorrectly documents the return values for _bios_equiplist. In the
  13962.  list of return values, it states that bit 13 is as follows:
  13963.  
  13964.      True (1) if and only if a serial printer is installed.
  13965.  
  13966.  This is only true if you have an IBM PCjr. On PC XT type machines,
  13967.  this value reports regardless of whether or not you have an internal
  13968.  modem installed.
  13969.  
  13970.  As a result, for PC XT machines, this line should read as follows:
  13971.  
  13972.     True (1) if and only if an internal modem is installed.
  13973.  
  13974.  This error also exists in the QuickC Versions 1.00 and 1.01 run-time
  13975.  library reference manuals and in the QuickC Version 2.00 on-line help.
  13976.  
  13977.  
  13978.  330. Macros max and min Incorrectly Listed as Functions
  13979.  
  13980.  Product Version(s): 5.00 5.10 | 5.10
  13981.  Operating System:   MS-DOS    | OS/2
  13982.  Flags: ENDUSER | docerr
  13983.  Last Modified: 16-MAY-1989    ArticleIdent: Q41610
  13984.  
  13985.  Page 181, section 8.3.2 of the "Microsoft C 5.1 Optimizing Compiler
  13986.  User's Guide" incorrectly lists max and min as functions that have
  13987.  intrinsic forms.
  13988.  
  13989.  As correctly noted in the "Microsoft C 5.1 Optimizing Compiler
  13990.  Run-Time Library Reference" on Pages 413 and 429, max and min are
  13991.  macros defined in the include file stdlib.h.
  13992.  
  13993.  
  13994.  331. Documentation on Global Variable _osversion Is Incomplete
  13995.  
  13996.  Product Version(s): 5.00 5.10
  13997.  Operating System:   MS-DOS
  13998.  Flags: ENDUSER | s_quickc
  13999.  Last Modified: 16-MAY-1989    ArticleIdent: Q41689
  14000.  
  14001.  Page 36 of the "Microsoft C 5.10 Optimizing Compiler Run-Time Library
  14002.  Reference" states the global variable _osversion "provides the
  14003.  complete version number" of DOS the program is running under. This
  14004.  information is correct, but the format of _osversion is not mentioned.
  14005.  
  14006.  The high-order byte of _osversion is the "minor" version number, or
  14007.  _osminor. The low-order byte is the "major" version number, or
  14008.  _osmajor.
  14009.  
  14010.  If you were to write out these values in hex on a system running DOS
  14011.  Version 3.30 your output would be as follows:
  14012.  
  14013.     _osversion = 1e03
  14014.     _osminor   = 1e    (30 in decimal)
  14015.     _osmajor   = 03
  14016.  
  14017.  See the C run-time library reference guide, Page 36 for more
  14018.  information.
  14019.  
  14020.  
  14021.  332. Using ANSI Escape Sequences in Microsoft C
  14022.  
  14023.  Product Version(s): 5.00 5.10
  14024.  Operating System:   MS-DOS
  14025.  Flags: ENDUSER | S_QuickC
  14026.  Last Modified: 17-MAY-1989    ArticleIdent: Q41701
  14027.  
  14028.  Question:
  14029.  
  14030.  How can I control the screen display using ANSI.SYS escape sequences
  14031.  in my C program? For example, how can I clear the screen using the
  14032.  escape sequences?
  14033.  
  14034.  Response:
  14035.  
  14036.  The easiest way to use ANSI escape sequences is to use them in the
  14037.  printf statement, as follows:
  14038.  
  14039.  #include <stdio.h>
  14040.  
  14041.  /* ESC[2J escape sequence clears the screen;
  14042.     \033 represents the octal code for ESC */
  14043.  
  14044.  #define  CLEAR "\033[2J"
  14045.  main()
  14046.  {
  14047.   printf ("%s screen is now cleared",CLEAR);
  14048.  }
  14049.  
  14050.  The best source of information on different escape sequences is "The
  14051.  MS-DOS Encyclopedia," Pages 731-738.
  14052.  
  14053.  Note: For escape sequences to work correctly, ANSI.SYS must be
  14054.  installed.
  14055.  
  14056.  
  14057.  333. Missing Closing ")" on Macro Causes C1004 Unexpected-EOF Error
  14058.  
  14059.  Product Version(s): 5.10    | 5.10
  14060.  Operating System:   MS-DOS  | OS/2
  14061.  Flags: ENDUSER | s_quickc
  14062.  Last Modified: 16-MAY-1989    ArticleIdent: Q42019
  14063.  
  14064.  The Microsoft C Version 5.10 Optimizing Compiler generates the
  14065.  following error message when the compiler encounters an incomplete
  14066.  macro invocation:
  14067.  
  14068.     fatal error C1004: unexpected EOF
  14069.  
  14070.  A macro in the program missing a closing-right parenthesis causes this
  14071.  error to occur. The Microsoft Quick C Compiler Version 2.00 also
  14072.  generates this error. Microsoft C Versions 5.00 and 4.00 and QuickC
  14073.  Version 1.01 generate the following error:
  14074.  
  14075.     C1057 unexpected EOF in macro expansion ( missing ')'? )
  14076.  
  14077.  Now the macro expander uses the same code to read characters when
  14078.  looking for an actual as it does to read any character. When we get
  14079.  the EOF, we cannot distinguish between a macro or the end of the code.
  14080.  This is correct behavior for C Version 5.10.
  14081.  
  14082.  The following is a sample piece of code that demonstrates this error:
  14083.  
  14084.  #include <stdio.h>
  14085.  #define add(wx, wy)  (wx) + (wy)
  14086.  void main(void)
  14087.  {
  14088.  int i;
  14089.  i = add( 1, 2 );
  14090.  printf( "i = %d\n", i );
  14091.  
  14092.  i = add( 1, 2 ;                 /* Causes C1004: unexpected EOF */
  14093.  
  14094.  printf( "Hello World\n" );
  14095.  for( i = 0; i < 10; i++ )
  14096.          {
  14097.          printf( "i + 10 = %d\n", add( i, 10 ) );
  14098.          }
  14099.  }
  14100.  
  14101.  
  14102.  
  14103.  334. Incorrect Usage of /o Switch in "Peter Norton's Inside OS/2"
  14104.  
  14105.  Product Version(s): 5.10
  14106.  Operating System:   OS/2
  14107.  Flags: ENDUSER | docerr
  14108.  Last Modified: 16-MAY-1989    ArticleIdent: Q42072
  14109.  
  14110.  "Peter Norton's Inside OS/2" book written by Peter Norton and Robert
  14111.  Lafore, published by Brady, contains examples of OS/2 programming that
  14112.  were written and compiled using the Microsoft C Optimizing compiler
  14113.  Version 5.10. Page 536 of the book states the following:
  14114.  
  14115.     The -o option prevents the compiler from thinking that the global
  14116.     variables have been defined more than once.
  14117.  
  14118.  This is incorrect. The /o option is an undocumented compiler switch
  14119.  that allows you to name the executable file. It is the same as the /Fe
  14120.  compiler switch.
  14121.  
  14122.  
  14123.  335. Second fscanf Is Skipped During Run Time
  14124.  
  14125.  Product Version(s): 5.00   | 5.10
  14126.  Operating System:   MS-DOS | OS/2
  14127.  Flags: ENDUSER | S_QuickC
  14128.  Last Modified: 25-MAY-1989    ArticleIdent: Q42075
  14129.  
  14130.  Question:
  14131.  
  14132.  I am using fscanf to read from the keyboard. Why is the second fscanf
  14133.  is skipped in the program below during run time?
  14134.  
  14135.  Response:
  14136.  
  14137.  The following is stated in the "Microsoft C 5.1 Optimizing Compiler
  14138.  Run-Time Library Reference" on Page 503 (in the description of the
  14139.  char format specifier):
  14140.  
  14141.     White-space characters that are ordinarily skipped are read when %c
  14142.     is specified; to read the next non-white-space character, use %1s.
  14143.  
  14144.  Note: You need an array of two characters for %1s because scanf will
  14145.  also put a terminating null in the string.
  14146.  
  14147.  Thus, after the first character is read in the example below, the
  14148.  following newline (e.g. linefeed, 0A hex) that is still in the C file
  14149.  buffer for stdin is read by the second fscanf (or scanf), causing the
  14150.  "second" prompt to be skipped during run time. The following is an
  14151.  example:
  14152.  
  14153.  #include <stdio.h>
  14154.  main()
  14155.  {
  14156.    char a,b[2];
  14157.    do
  14158.     {
  14159.       fprintf (stdout, "\n Enter first single character\n");
  14160.       fscanf (stdin, "%c", &a);
  14161.  
  14162.       fprintf (stdout, "second\n");
  14163.       fscanf (stdin, "%c", b);       /*this will get the new-line*/
  14164.     }
  14165.     while (b != 'y');
  14166.  }
  14167.  
  14168.  To work around this problem, use the format specifier %1s instead of
  14169.  %c. Don't forget to pass scanf an array of two characters.
  14170.  
  14171.  Alternately, the fflush() function may be used to flush all characters,
  14172.  including white space, out of the specified buffer after each fscanf or
  14173.  scanf, or flushall() may be used to flush all file buffers. However, using
  14174.  these functions wouldn't leave any characters in the file buffer for
  14175.  later scanfs.
  14176.  
  14177.  
  14178.  336. Getting 43-line Mode for C and QuickC Graphics
  14179.  
  14180.  Product Version(s): 5.10
  14181.  Operating System:   MS-DOS
  14182.  Flags: ENDUSER | s_quickc
  14183.  Last Modified: 15-JAN-1990    ArticleIdent: Q42079
  14184.  
  14185.  The Microsoft C Version 5.10 Optimizing Compiler README.DOC file
  14186.  states the following:
  14187.  
  14188.     The graphics library new functions correctly in 43-line mode on an
  14189.     EGA, and in 43-line, 50-line, and 60-line modes on a VGA.
  14190.  
  14191.  This information is correct; however, it does not state that you must
  14192.  write your own interrupt routine to set the video mode to support
  14193.  this.
  14194.  
  14195.  The following program demonstrates using Int 10H, Function 11H,
  14196.  Subfunction 23H to set an EGA system into 43-line mode. The interrupt
  14197.  call must be made BEFORE the call to _setvideomode(). If the routine
  14198.  is called after _setvideomode(), the text height is changed, but the
  14199.  program uses only the first 25 lines of the screen.
  14200.  
  14201.  The same procedure also works with the QuickC Version 2.00
  14202.  Presentation Graphics package, for placing additional text (with
  14203.  _outtext) around the chart. It does not change any of the default text
  14204.  (which already has the text height of 43-line mode), or change the
  14205.  appearance of the chart, but it allows additional text to be added
  14206.  around the chart in the smaller font to create a uniform appearance.
  14207.  
  14208.  The following is a sample program that demonstrates 43-line mode:
  14209.  
  14210.  /* program line43.c */
  14211.  
  14212.  #include <conio.h>
  14213.  #include <stdio.h>
  14214.  #include <graph.h>
  14215.  #include <dos.h>
  14216.  #include <process.h>
  14217.  
  14218.  union REGS inregs, outregs;
  14219.  struct SREGS segregs;
  14220.  int result;
  14221.  
  14222.  void main(void)
  14223.  {
  14224.    inregs.h.ah = 0x11;      /*load Function # into AH register       */
  14225.    inregs.h.al = 0x23;      /*load SubFunc # into AL register        */
  14226.    inregs.h.bl = 0x03;      /*load constant for 43-line mode into BL */
  14227.                             /*For 50-line mode, use                  */
  14228.                             /*       inregs.h.bl=0x00;               */
  14229.                             /*       inregs.h.dl=0x32;               */
  14230.  
  14231.    int86x(0x10, &inregs, &outregs, &segregs);  /* call interrupt */
  14232.  
  14233.    _setvideomode(_ERESCOLOR);   /* 640x350 EGA graphics mode         */
  14234.                                 /* For VGA w/50 lines, change to:    */
  14235.                                 /* _setvideomode(_VRES16COLOR);      */
  14236.    _settextposition(30,30);
  14237.    _outtext("this should be tiny text!");
  14238.    while(!kbhit());
  14239.    _setvideomode(_DEFAULTMODE);  /* restore to default mode  */
  14240.  
  14241.  Note: The "IBM ROM BIOS" quick-reference guide states that this
  14242.  function should be used only AFTER a _setvideomode command. However,
  14243.  this does not work effectively with the C graphics library.
  14244.  
  14245.  
  14246.  337. Clarification of fcvt() Function
  14247.  
  14248.  Product Version(s): 5.00 5.10 | 5.10
  14249.  Operating System:   MS-DOS    | OS/2
  14250.  Flags: ENDUSER | s_quickc
  14251.  Last Modified: 17-MAY-1989    ArticleIdent: Q42453
  14252.  
  14253.  This article is meant to clarify the description of the fcvt()
  14254.  function in the "Microsoft C for the MS-DOS Operating System: Run-Time
  14255.  Library Reference," Pages 251-252.
  14256.  
  14257.  The fcvt() function converts a floating-point number to a
  14258.  null-terminated character string. The number of digits converted
  14259.  depends on the second parameter passed. This second parameter is
  14260.  called "count" for the remainder of this article.
  14261.  
  14262.  The function is designed to return all the digits to the left of the
  14263.  decimal point, and then count digits to the right. Once the string is
  14264.  converted, all leading zeros are removed unless the number passed was
  14265.  zero (see Example 4 below). The string will be terminated with the
  14266.  "/0" character. The decimal point is not included in the string, and
  14267.  its position can be obtained from the third parameter (see the
  14268.  documentation).
  14269.  
  14270.  Based on this description, the following examples apply. In all cases,
  14271.  count = 8. The examples are as follows:
  14272.  
  14273.  1. Number passed: 3.667      String returned: "366700000\0"
  14274.  
  14275.     Nine digits are returned: one for the number to the left of the
  14276.     decimal point, eight more because of the count parameter.
  14277.  
  14278.  2. Number passed: 3.67E-08   String returned: "3\0"
  14279.  
  14280.     In this case, only "3" is returned because after the number is
  14281.     converted, all the leading zeros are removed.
  14282.  
  14283.  3. Number passed: 1.023E-12  String returned: "\0"
  14284.  
  14285.     In this case, a NULL string is returned because only zeros are left
  14286.     after the conversion, and these are all removed from the resulting
  14287.     string. If error checking were being performed, this would indicate
  14288.     a conversion underflow.
  14289.  
  14290.  4. Number passed: 0          String returned: "00000000\0"
  14291.  
  14292.     This is the only "special" case. Eight zeros are returned so that
  14293.     error checking can be performed easily.
  14294.  
  14295.  
  14296.  338. C Function _dos_setdrive Returns "5" Drives in the System
  14297.  
  14298.  Product Version(s): 5.00 5.10
  14299.  Operating System:   MS-DOS
  14300.  Flags: ENDUSER | QuickC
  14301.  Last Modified: 17-MAY-1989    ArticleIdent: Q42461
  14302.  
  14303.  Question:
  14304.  
  14305.  Why does the C function _dos_setdrive always return "5", indicating
  14306.  that I have five drives in my system, when in fact I only have two?
  14307.  
  14308.  Response:
  14309.  
  14310.  The run-time function _dos_setdrive takes two arguments, as follows:
  14311.  
  14312.     void _dos_setdrive (drivenum, drives)
  14313.  
  14314.  The drives argument indicates the total number of drives in the
  14315.  system. This means that it will return the number of possible drives
  14316.  in the system. The system call Int 21 function 0x0E that _dos_setdrive
  14317.  uses to get this information will return a value of either five drives
  14318.  in the system or the drive code corresponding to the LASTDRIVE entry
  14319.  in CONFIG.SYS, whichever is greater. Without setting
  14320.  lastdrive="character" in your CONFIG.SYS, the default "lastdrive" is
  14321.  E, which corresponds to five drives possible. This is why
  14322.  _dos_setdrive will return "5" when you do not have five physical
  14323.  drives in the system.
  14324.  
  14325.  For example, the following line in CONFIG.SYS will cause a return of
  14326.  26, indicating that 26 drives are present in the system:
  14327.  
  14328.     lastdrive=z
  14329.  
  14330.  Therefore, the function _dos_setdrive is working correctly; it is the
  14331.  system call 0x0E that is returning such information.
  14332.  
  14333.  Note: The above information applies only to DOS Versions 3.x and 4.x.
  14334.  Under DOS 2.x, the actual number of drives present in the system will
  14335.  be reported.
  14336.  
  14337.  
  14338.  339. Inconsistent Warnings: C4049 and C4024 in C and QuickC
  14339.  
  14340.  Product Version(s): 5.10   | 5.10
  14341.  Operating System:   MS-DOS | OS/2
  14342.  Flags: ENDUSER | s_QuickC
  14343.  Last Modified:  1-JUN-1989    ArticleIdent: Q42562
  14344.  
  14345.  When compiled with warning level one or higher, the following code
  14346.  produces a single warning under the C 5.10 compiler and an additional
  14347.  warning under QuickC 2.00:
  14348.  
  14349.      /*  Inconsistent warning example
  14350.       */
  14351.      void fozzy( short foo, short *spud );
  14352.      void winky( int   foo, int   *spud );
  14353.  
  14354.      void main( void )
  14355.      {
  14356.          short sTest;
  14357.          short sPoint;
  14358.  
  14359.          fozzy( sTest, &sPoint );
  14360.          winky( sTest, &sPoint );
  14361.      }
  14362.  
  14363.  The warning emitted by both compilers is as follows:
  14364.  
  14365.     warning C4049: 'argument' : indirection to different types
  14366.  
  14367.  QuickC also produces the following warning:
  14368.  
  14369.     warning C4024: 'winky' : different types : parameter 2
  14370.  
  14371.  In both cases, the compilers dislike the second parameter in the call
  14372.  to winky. Winky is prototyped as accepting a pointer to an integer and
  14373.  is being passed a pointer to a short.
  14374.  
  14375.  These warnings are inconsistent because the compiler is not upset
  14376.  about winky being passed a short as its first parameter, when it has
  14377.  been prototyped as accepting an integer. If the compiler considers a
  14378.  short and an integer to be the same for the first parameter, pointers
  14379.  to these types should be considered the same for the second parameter.
  14380.  
  14381.  These generated warnings are expected behavior for both C and QuickC.
  14382.  Although integers and shorts are the same under Microsoft's
  14383.  implementation of C, they should not be considered to be the same. The
  14384.  only restriction on the size of the short given by the ANSI standard
  14385.  is that it not be longer than an integer. Code should be written with
  14386.  this in mind to maintain ANSI compatibility and prevent problems with
  14387.  future compilers, where integers might not be the same size as shorts.
  14388.  
  14389.  
  14390.  340. Using Near Addresses in Interrupt Handlers in C
  14391.  
  14392.  Product Version(s): 5.10
  14393.  Operating System:   MS-DOS
  14394.  Flags: ENDUSER |
  14395.  Last Modified: 17-MAY-1989    ArticleIdent: Q42597
  14396.  
  14397.  When the Microsoft C Compiler compiles the sample program below for
  14398.  the small or medium memory model, it gives the following warning:
  14399.  
  14400.     warning C4058: address of frame variable taken, DS != SS
  14401.  
  14402.  The sample program is as follows:
  14403.  
  14404.  /* sample program */
  14405.  void interrupt far handler (void) ;
  14406.  void foo (char *) ;
  14407.  
  14408.  void interrupt far handler (void)
  14409.  {
  14410.  char ch ;
  14411.  foo (&ch) ;
  14412.  }
  14413.  
  14414.  void foo (char * ptr)   /* a trivial function */
  14415.  {
  14416.  *ptr = 'a' ;
  14417.  }
  14418.  
  14419.  The warning is generated because the Microsoft C Compiler assumes that
  14420.  DS is equal to SS. Because the stack segment SS could possibly be
  14421.  changed in an interrupt service routine, the compiler gives a warning
  14422.  when a near address that refers to a stack location is passed to a
  14423.  function.
  14424.  
  14425.  In general, in the small and medium memory models, data pointers are
  14426.  defaulted to be near unless the "far" keyword is used. In the example
  14427.  above, the function "foo" is expecting a near address that is a 16-bit
  14428.  offset. A function such as "foo" has no way to tell if the near
  14429.  pointer passed to it is an offset relative to the data segment or the
  14430.  stack segment. Therefore, the C compiler makes the assumption that an
  14431.  offset by itself is always relative to the default data segment. This
  14432.  is not a problem in the normal case, where we can depend on the
  14433.  assumption that the C compiler makes SS equal to DS. However, in the
  14434.  example above, the stack segment could be changed in the interrupt
  14435.  handling routine; therefore, the compiler warns you that the code may
  14436.  not work correctly.
  14437.  
  14438.  If the memory model is large or compact, or if the "far" keyword is
  14439.  used when foo's formal parameter is declared, the compiler will not
  14440.  give any warnings. When "foo" is called, an address with the stack
  14441.  segment and the offset will be passed to the function automatically.
  14442.  Declaring the stack variable "ch" as static will also avoid the
  14443.  problem. The corrected source code is as follows:
  14444.  
  14445.  /* sample program */
  14446.  void interrupt far handler (void) ;
  14447.  void foo (char *) ;
  14448.  
  14449.  void interrupt far handler (void)
  14450.  {
  14451.  static char ch ;
  14452.  foo (&ch) ;
  14453.  }
  14454.  
  14455.  void foo (char * ptr)   /* a trivial function */
  14456.  {
  14457.  *ptr = 'a' ;
  14458.  }
  14459.  
  14460.  
  14461.  341. _imagesize Formula Documented Incorrectly for Some Video Modes
  14462.  
  14463.  Product Version(s): 5.00 5.10
  14464.  Operating System:   MS-DOS
  14465.  Flags: ENDUSER | s_quickc docerr
  14466.  Last Modified: 17-MAY-1989    ArticleIdent: Q42600
  14467.  
  14468.  The formula given on Page 362 of the "Microsoft C for the MS-DOS
  14469.  Operating System: Run-Time Library Reference" for Optimizing C Version
  14470.  5.x and QuickC Version 1.x, and on Page 133 of the "Microsoft QuickC
  14471.  2.00 Graphics Library Reference" is incorrect for most color EGA and
  14472.  VGA video modes. The formula given is as follows:
  14473.  
  14474.     xwid = abs(x1-x2)+1;
  14475.     ywid = abs(y1-y2)+1;
  14476.     size = 4+((long) ((xwid*bits_per_pixel+7)/8)*(long)ywid);
  14477.  
  14478.  This formula is accurate only for the following modes:
  14479.  
  14480.     _MRES4COLOR
  14481.     _MRESNOCOLOR
  14482.     _HRESBW
  14483.     _VRES2COLOR
  14484.     _MRES256COLOR
  14485.     _HERCMONO
  14486.     _ORESCOLOR
  14487.  
  14488.  However, for most EGA and VGA color graphics modes, the correct
  14489.  formula is as follows:
  14490.  
  14491.     xwid = abs(x1-x2)+1;
  14492.     ywid = abs(y1-y2)+1;
  14493.     size = 4 + ((bits_per_pixel * (long) ((xwid+7)/8)) * ywid);
  14494.  
  14495.  This formula should be used exclusively for modes that utilize bit
  14496.  planes. These modes are as follows:
  14497.  
  14498.     _MRES16COLOR
  14499.     _HRES16COLOR
  14500.     _ERESCOLOR
  14501.     _VRES16COLOR
  14502.  
  14503.  Either formula is accurate for the following modes:
  14504.  
  14505.     _HRESBW
  14506.     _VRES2COLOR
  14507.     _HERCMONO
  14508.     _ORESCOLOR
  14509.  
  14510.  A call to _getvideoconfig will determine the current video mode. This
  14511.  call is also necessary to determine the bits_per_pixel value.
  14512.  
  14513.  The following is an example of values that will yield an incorrect
  14514.  result in _VRES16COLOR mode:
  14515.  
  14516.     x1 = 0;  y1 = 0;
  14517.     x2 = 4;  y2 = 5;
  14518.  
  14519.  Note that for all cases, _imagesize does return the correct value.
  14520.  Only the formula given in the reference manuals is incorrect.
  14521.  
  14522.  The formula used internally by the _imagesize function is as follows:
  14523.  
  14524.     xwid = abs(x1-x2)+1;
  14525.     ywid = abs(y1-y2)+1;
  14526.     size = 4+(bits_per_plane*(long) ((xwid*linear_bits_per_pixel+7)/8)*ywid);
  14527.  
  14528.  This formula is useful only for lending understanding of how the two
  14529.  prior formulas are derived. It cannot be used in a C program for the
  14530.  following reasons:
  14531.  
  14532.  1. In this formula, linear_bits_per_pixel is the actual number of
  14533.     linear bits required to store a pixel. In the color EGA and VGA
  14534.     modes listed, this is not equivalent to the bitsperpixel field of
  14535.     the videoconfig structure. There is no way to determine this value
  14536.     within C.
  14537.  
  14538.  2. There is no way to determine the bits_per_plane value within C.
  14539.  
  14540.  The formula given on Page 392 of the run-time library reference is
  14541.  correct for CGA, single-color, and _MRES256COLOR modes because bit
  14542.  planes are not utilized in storing graphic images. That is,
  14543.  bits_per_plane is equal to 1. Therefore, this factor may be simplified
  14544.  out of the equation.
  14545.  
  14546.  The formula given on Page 392 of the run-time library reference fails
  14547.  on the listed EGA and VGA modes because bit planes are implemented in
  14548.  storing graphics images under those modes. That is, bits_per_plane is
  14549.  greater than 1. Also, linear_bits_per_pixel is not equivalent to the
  14550.  bitsperpixel field of the videoconfig structure.
  14551.  
  14552.  In elaborating on the bitsperpixel field of the videoconfig structure,
  14553.  this value is as follows:
  14554.  
  14555.     vc.bitsperpixel = linear_bits_per_pixel * bits_per_plane;
  14556.  
  14557.  For more information on bit planes and pixel maps, refer to the
  14558.  "Programmer's Guide to PC & PS/2 Video Systems" by Richard Wilton,
  14559.  Pages 87-91.
  14560.  
  14561.  
  14562.  342. Not Including MALLOC.H in Compact, Large Model Causes Problems
  14563.  
  14564.  Product Version(s): 5.00 5.10 | 5.10
  14565.  Operating System:   MS-DOS    | OS/2
  14566.  Flags: ENDUSER | S_QuickC
  14567.  Last Modified: 30-MAY-1989    ArticleIdent: Q42756
  14568.  
  14569.  It is vital in the compact- and large-memory models that the malloc()
  14570.  function be prototyped as returning a four-byte type (preferably a far
  14571.  pointer, of course). The proper method in Microsoft C is to include
  14572.  the header file MALLOC.H. This prototypes malloc() as returning a void
  14573.  pointer.
  14574.  
  14575.  The default data-pointer size in the compact and large models is 32
  14576.  bits. The default return type of any function, including malloc, when
  14577.  it is not prototyped is a 16-bit short integer. Thus, the segment
  14578.  portion of a far address will be destroyed unless the compiler knows
  14579.  it is dealing with a 32-bit type.
  14580.  
  14581.  If you attempt to use the Unix style of including MEMORY.H rather than
  14582.  MALLOC.H, you will encounter problems at run time. MEMORY.H does not
  14583.  prototype any of the memory allocation functions; it only prototypes
  14584.  memory copy and move functions. In a segmented architecture that can
  14585.  have data and code pointers of different sizes, this may have serious
  14586.  ramifications. In the case of a large- or compact-model program such
  14587.  as the following, the call to malloc() will produce the following code
  14588.  fragment:
  14589.  
  14590.      #include <memory.h>
  14591.      main()
  14592.      {
  14593.          char    *addr;
  14594.          size_t  nbytes = 100;
  14595.  
  14596.          addr = (char *) malloc( nbytes );
  14597.      }
  14598.  
  14599.  The call to malloc() produces the following code fragment:
  14600.  
  14601.              push    Word Ptr [nbytes]
  14602.              call    _malloc
  14603.              add     sp, +02
  14604.              cwd
  14605.              mov     Word Ptr [addr], AX
  14606.              mov     Word Ptr [bp-06], DX
  14607.  
  14608.  If MALLOC.H had been included, then the CWD (Convert Word to Double)
  14609.  instruction would not be present. CWD sign extends the AX register
  14610.  into the DX register in an attempt to convert the 16-bit integer in AX
  14611.  to a 32-bit data pointer. This trashes the segment returned by
  14612.  malloc() in DX. The resultant pointer will typically point to segment
  14613.  0x0000, meaning that in DOS the interrupt table will be trashed and in
  14614.  OS/2 the program will GP fault when an assignment is made to the
  14615.  allocated memory.
  14616.  
  14617.  Note: The compiler will also produce data conversion warnings at
  14618.  warning level 1 or higher when such a program is compiled. Paying
  14619.  attention to these warnings generally eliminates problems in
  14620.  converting C programs from other systems.
  14621.  
  14622.  
  14623.  343. Use /Op to Avoid Floating-Point Optimization Problem
  14624.  
  14625.  Product Version(s): 5.10   | 5.10
  14626.  Operating System:   MS-DOS | OS/2
  14627.  Flags: ENDUSER | SR# G890216-12181
  14628.  Last Modified: 17-MAY-1989    ArticleIdent: Q42761
  14629.  
  14630.  The program below fails when compiled without an /O? option, but works
  14631.  if compiled with /Od. The problem seems to be in the conversion of the
  14632.  double to int -- the rounding seems to be done incorrectly.
  14633.  
  14634.  When the code is optimized, the result of the division is kept on the
  14635.  floating-point stack rather than being stored into memory and reloaded
  14636.  onto the stack. This causes precision problems because the numbers on
  14637.  the stack are stored in extended (10- byte) precision while doubles in
  14638.  memory are stored using 8 bytes.
  14639.  
  14640.  Note that the constant 23.31 cannot be represented exactly in the
  14641.  binary floating-point scheme used by Microsoft C. The fact that it is
  14642.  represented slightly small and then multiplied by 100 (magnifying the
  14643.  error) contributes to this problem.
  14644.  
  14645.  To avoid this problem, use the /Op option when compiling. The /Op
  14646.  switch forces in-memory storage of intermediate results. /Op can be
  14647.  combined with other optimizations (for instance, /Oxp).
  14648.  
  14649.  Program Example
  14650.  
  14651.  /*
  14652.  
  14653.    When the following program is compiled using default optimization,
  14654.    the program prints 2330 instead of 2331 (as it is supposed to.)
  14655.    Also, if the commented line is uncommented, the program works
  14656.    correctly with default optimization.
  14657.  
  14658.  */
  14659.  
  14660.  #include <stdio.h>
  14661.  void main(void)
  14662.  {
  14663.      int a;
  14664.      double f;
  14665.      f = 23.31;
  14666.      f = f * 100;
  14667.      /* printf(">%g<\n", f); */
  14668.      a = (int)f;
  14669.      printf(">%d<\n",a);
  14670.      return;
  14671.  }
  14672.  
  14673.  
  14674.  344. Patches of Floating-Point Instructions at Run Time Are Normal
  14675.  
  14676.  Product Version(s): 5.10
  14677.  Operating System:   MS-DOS
  14678.  Flags: ENDUSER | SR# G890217-12193
  14679.  Last Modified: 30-MAY-1989    ArticleIdent: Q42762
  14680.  
  14681.  Question:
  14682.  
  14683.  I have noticed that memory overwrites occur in the library routine
  14684.  i8_input. While debugging the program under CodeView with the
  14685.  assembler listing, I noticed that after executing into the code, the
  14686.  first 2 bytes of each instruction beginning with a hex CD are
  14687.  overwritten. The C statement that generated the assembler code with
  14688.  the problem in it was an "fscanf" function call.
  14689.  
  14690.  Below is an listing example of what is occurring:
  14691.  
  14692.  Before
  14693.  ------
  14694.  
  14695.  7E1F:4266 CD35C0       INT 35 ; FLD     ST(0)
  14696.  7E1F:4269 CD35E1       INT 35 ; FABS
  14697.  7E1F:426C CD372E7425   INT 37 ; FLD     TByte Ptr [__chbuf+5C (2574)]
  14698.  
  14699.  After
  14700.  -----
  14701.  
  14702.  7E1F:4266 90           NOP
  14703.  7E1F:4267 D9C0         FLD      ST(0)
  14704.  7E1F:4269 90           NOP
  14705.  7E1F:426A D9E1         FABS
  14706.  7E1F:426C 90           NOP
  14707.  7E1F:426D DB2E7425     FLD      TByte Ptr [__chbuf+5C (2574)]
  14708.  
  14709.  Response:
  14710.  
  14711.  The behavior you describe is quite normal and nothing to worry about.
  14712.  Our floating-point package works by generating the INT instructions
  14713.  you noticed. When these instructions are executed, the routine they
  14714.  call replaces the INT instructions with the either library calls to
  14715.  the emulator library or the actual 80 x 87 floating-point
  14716.  instructions, depending on whether or not a coprocessor is installed.
  14717.  
  14718.  When the instructions are executed again, there is no overhead for
  14719.  determining whether on not a coprocessor is installed: the proper
  14720.  instructions have been patched into place already. This patching
  14721.  occurs even if the -FPi87 option has been selected.
  14722.  
  14723.  You can force in-line 8087 instructions to be put into your code.
  14724.  For information on this technique, query on the following keywords:
  14725.  
  14726.     in-line 8087 instructions
  14727.  
  14728.  There is no need to do this if your code is going to run under DOS or
  14729.  OS/2. Although this article mainly discusses FORTRAN, it applies to C
  14730.  as well because the two languages use the same floating-point library.
  14731.  
  14732.  This code modification occurs only under DOS. Under OS/2, coprocessor
  14733.  instructions (such as in the second listing) are always generated. If a
  14734.  coprocessor is not present at execution, the instructions cause
  14735.  exceptions that are handled by the floating-point emulator software.
  14736.  
  14737.  Note: Such code modification is impossible under OS/2 because there is
  14738.  no way to dynamically change a code segment under OS/2, although it is
  14739.  possible to cause a data segment to be executed.
  14740.  
  14741.  
  14742.  345. Opening a C File When Disk Is Write Protected
  14743.  
  14744.  Product Version(s): 5.00 5.10
  14745.  Operating System:   MS-DOS
  14746.  Flags: ENDUSER | s_quickc
  14747.  Last Modified: 17-MAY-1989    ArticleIdent: Q42773
  14748.  
  14749.  With the run-time library in the Microsoft C Optimizing Compiler, a
  14750.  program can open an existing file for both read and write when the
  14751.  floppy disk is write protected. The following statement may be used to
  14752.  open the file:
  14753.  
  14754.     handle = open ("a:test.dat", O_RDWR | O_TRUNC) ;
  14755.  
  14756.  No error condition is returned and no hard error occurs. However,
  14757.  later, when the program tries to write to the file handle or even to
  14758.  close the file without writing, a hard error will occur with the
  14759.  following message:
  14760.  
  14761.     Writing protect error writing drive A:
  14762.     Abort, Retry, Fail?
  14763.  
  14764.  This is not a problem with the open() function in the Microsoft C
  14765.  run-time library. The low-level DOS function call that is used to
  14766.  implement open() does not check for a write-protect error. When the
  14767.  file is to be closed by close(), the internal buffer has to be flushed
  14768.  to the disk. No low-level DOS function can close a file without
  14769.  flushing its associated buffer.
  14770.  
  14771.  Workaround
  14772.  
  14773.  There is no direct way to detect the write-protect condition. An
  14774.  indirect workaround is to open a file with the mode to be O_CREAT, as
  14775.  follows:
  14776.  
  14777.      open ( "a:chk00000.xxx", O_CREAT, S_IWRITE | S_IREAD) ;
  14778.  
  14779.  A hard error will occur, which can be captured by a user-implemented
  14780.  and installed hard-error handler. This handler will override the
  14781.  printing of the hard-error message on the user screen. The open()
  14782.  function does return -1 when it regains the control from the
  14783.  hard-error handle. If the file was opened successfully, it may be
  14784.  removed at the end of the program.
  14785.  
  14786.  The following sample program demonstrates checking of a
  14787.  write-protected disk:
  14788.  
  14789.  /* sample program */
  14790.  #include <fcntl.h>
  14791.  #include <sys\types.h>
  14792.  #include <sys\stat.h>
  14793.  #include <io.h>
  14794.  #include <stdio.h>
  14795.  #include <dos.h>
  14796.  void far handler ( unsigned, unsigned, unsigned far * ) ;
  14797.  
  14798.  #define PROTECTED 1
  14799.  #define OTHER     2
  14800.  
  14801.  int Flag = 0 ;
  14802.  
  14803.  char * ChkName = "a:qwlbqwsi.ufp" ;     /* dummy file name */
  14804.  
  14805.  /* Note:
  14806.  ** If the file happens to exist, the hard error will not occur.
  14807.  ** The program will output "Disk is not write-protected."
  14808.  */
  14809.  
  14810.  void main(void)
  14811.  {
  14812.  int FileHandle;
  14813.  
  14814.  _harderr ( handler ) ;              /* set up hard error handler */
  14815.  
  14816.  FileHandle = open ( ChkName, O_CREAT, S_IWRITE | S_IREAD ) ;
  14817.  
  14818.  if ( FileHandle == -1 )             /* check write-protect */
  14819.       {
  14820.       switch ( Flag ) {              /* may be set by the handler */
  14821.          case PROTECTED :
  14822.              puts ( "Disk in drive A: is write-protected." ) ;
  14823.              break ;
  14824.          case OTHER :
  14825.              puts ( "A another hard error has occurred." ) ;
  14826.              break ;
  14827.          default :
  14828.              puts ( "Error opening file (non hard error.)" ) ;
  14829.          }
  14830.       }
  14831.  else {
  14832.       puts ( "Disk is not write-protected." ) ;
  14833.       close ( FileHandle ) ;
  14834.       remove ( ChkName ) ;           /* delete the file */
  14835.       }
  14836.  }
  14837.  
  14838.  /*
  14839.          Hard error routine should be as short as possible
  14840.  */
  14841.  void far handler ( unsigned deverror, unsigned errcode,
  14842.                     unsigned far *devhdr )
  14843.  {
  14844.  if ( errcode == 0 )
  14845.      Flag = PROTECTED ;
  14846.  else
  14847.      Flag = OTHER ;              /* like drive door is open */
  14848.  
  14849.  _hardretn ( 0 ) ;
  14850.  }
  14851.  /* end of sample */
  14852.  
  14853.  Note: The argument 0 to _hardretn() is not significant in this
  14854.  program. Please refer to Page 351 of the "Microsoft C for the MS-DOS
  14855.  Operating System: Run-Time Library Reference" for Version 5.10 for
  14856.  more specific information regarding the _hardretn() function.
  14857.  
  14858.  
  14859.  346. C Compiler: _control87() and Modifying the Control Word
  14860.  
  14861.  Product Version(s): 5.00 5.10 | 5.10
  14862.  Operating System:   MS-DOS    | OS/2
  14863.  Flags: ENDUSER |
  14864.  Last Modified: 25-MAY-1989    ArticleIdent: Q42781
  14865.  
  14866.  Question:
  14867.  
  14868.  I want to mask off invalid arithmetic operation interrupts
  14869.  (EM_INVALID) from the math coprocessor using the _control87()
  14870.  function. However, after masking invalids with _control87() and
  14871.  confirming its value, invalids continue to be unmasked.
  14872.  
  14873.  Can I adjust the control word myself, or does the math package depend
  14874.  on a certain state of the control word?
  14875.  
  14876.  Response:
  14877.  
  14878.  You cannot mask or unmask certain bits with _control87(), even though
  14879.  it will report that it was successful. Also, modifying certain bits of
  14880.  the control word yourself (with the 80X87 instruction FLDCW) will
  14881.  corrupt all subsequent floating-point C run-time operations.
  14882.  
  14883.  The documentation in FPEXCEPT.DOC (which is contained in the C 5.10
  14884.  package) does state that denormals are always masked off and that
  14885.  invalids are never masked. It also states that bits 7, 6, 1, and 0 in
  14886.  the control word cannot be modified. It is true that these bits cannot
  14887.  be modified with the function _control87(); however, if you look at
  14888.  the control word with an assembly routine, you will see that the
  14889.  control word does not hold the same value as the C run time would have
  14890.  you believe.
  14891.  
  14892.  Invalid exceptions cannot be masked because the C run time uses them
  14893.  internally to handle extending the 80 x 87 floating-point stack beyond
  14894.  eight stack elements. If you try to mask invalid with the C run time,
  14895.  you will be told that you were successful, but the control word will
  14896.  not be changed at all. No invalid exceptions will ever reach you. If
  14897.  you try to mask invalid and an invalid exception occurs (which doesn't
  14898.  have anything to do with stack overflow or underflow), the C run time
  14899.  will check to see if you tried to mask invalid. If you did, the
  14900.  floating point routines will simply ignore the mask. If you mask
  14901.  invalid by setting the control word from an assembly routine with
  14902.  FLDCW, the run time will have stack problems.
  14903.  
  14904.  As for denormals, the denormal exception is never masked internally
  14905.  because every time the 80 x 87 encounters a denormal number, the
  14906.  emulator will try to convert it to a normalized number. This is the
  14907.  masked behavior on an 80387. Because this should not be changed (since
  14908.  it will break our math routines), you should treat denormals as if
  14909.  they are always masked. Thus, denormals always appear to be masked;
  14910.  you will never see a denormal exception, since they are all handled
  14911.  internally by the emulator.
  14912.  
  14913.  Therefore, denormals always appear to be masked unless you look at the
  14914.  control word on the chip directly, by using an FSTCW or CodeView. Also,
  14915.  it will appear that invalids can be masked, unless you look at the
  14916.  chip directly. If you do look at the chip directly, you will see that
  14917.  nothing has changed when trying to mask an invalid with _control87.
  14918.  Therefore, the code is functioning as expected. Both invalid and
  14919.  denormal are unmasked. If you look at the control word with FSTCW, you
  14920.  will see that the default control word is 1370h, instead of the 1332h
  14921.  returned by _control87. Also, if you send _control87(0x00ff,0x00ff),
  14922.  this function will tell you that the control word is set to 13FFh;
  14923.  however, FSTCW will reveal that the control word is really set to
  14924.  137Ch.
  14925.  
  14926.  Because the run time depends on certain settings of the control word,
  14927.  we do not want the run time to modify those settings. You can easily
  14928.  write an assembly routine to set the control word to anything you
  14929.  like, using FLDCW. It would not be to anyone's advantage to provide a
  14930.  floating-point function that would nullify all subsequent
  14931.  floating-point run time.
  14932.  
  14933.  We do not support the modification of the control-word bits mentioned
  14934.  above.
  14935.  
  14936.  For additional information on floating point exceptions, please refer
  14937.  to the file FPEXCEPT.DOC contained in the C 5.10 package.
  14938.  
  14939.  
  14940.  347. Fatal Error C1059: Out of Near Heap Space
  14941.  
  14942.  Product Version(s): 5.00   | 5.10
  14943.  Operating System:   MS-DOS | OS/2
  14944.  Flags: ENDUSER |
  14945.  Last Modified: 17-MAY-1989    ArticleIdent: Q42793
  14946.  
  14947.  Using the /Zg compiler option to generate function declarations from
  14948.  the function definitions can cause the following error:
  14949.  
  14950.     Fatal error C1059: Out of near heap space.
  14951.  
  14952.  You may be able to free more space on the near heap by invoking the
  14953.  compiler in two passes, as follows:
  14954.  
  14955.          cl /P filename.c
  14956.          cl /Zg /c /Tc filename.I
  14957.  
  14958.  The first pass processes the preprocessor statements and produces an
  14959.  intermediate file. The second pass generates the function declarations
  14960.  from the intermediate file.
  14961.  
  14962.  Both the preprocessor and the compiler /Zg option use the near heap.
  14963.  The preprocessor uses the near heap to evaluate macro expansions. The
  14964.  compiler /Zg option uses the near heap while producing the function
  14965.  declaration listing.
  14966.  
  14967.  
  14968.  348. Background Colors Limited to 0 Through 7 in Text Mode
  14969.  
  14970.  Product Version(s): 5.10
  14971.  Operating System:   MS-DOS
  14972.  Flags: ENDUSER | s_quickc
  14973.  Last Modified: 15-JAN-1990    ArticleIdent: Q42796
  14974.  
  14975.  The function _setbkcolor() displays only colors "0" through "7" when
  14976.  in text mode. This is a limit of the hardware, not the library
  14977.  function.
  14978.  
  14979.  Two bytes are allocated for each character displayed on a text 80 x 25
  14980.  screen. The first byte is the ASCII code of the character; the second
  14981.  is the attribute byte.
  14982.  
  14983.  The attribute byte contains the information about the foreground and
  14984.  background attributes of the character. Four bits of this byte are
  14985.  allocated for the foreground color. The most significant bit of the
  14986.  foreground color is set aside for intensity or highlight. However, of
  14987.  the 4 bits allocated for the background color, the most significant
  14988.  bit is reserved to indicate a blinking or a nonblinking state.
  14989.  
  14990.  The layout of the attribute bytes is as follows:
  14991.  
  14992.              7    6   5   4   3   2   1   0
  14993.           +----+------------+---+------------+
  14994.           | BL | background | I | foreground |
  14995.           +----+------------+---+------------+
  14996.  
  14997.  Since only 3 bits are used to indicate the background color, only
  14998.  numbers from 0 through 7 can be represented. For this reason, only
  14999.  colors 0 through 7 are available as background colors for
  15000.  _setbkcolor().
  15001.  
  15002.  On most display adapters, you can set the adapter such that the blink
  15003.  bit becomes a background intensity bit. See your hardware technical
  15004.  reference or the "Programmer's Guide to PC and PS/2 Video Systems"
  15005.  (Richard Wilton, Microsoft Press) for more information.
  15006.  
  15007.  
  15008.  349. Exception #13 at xxxx:xxxx Error Code 0 Caused by QEMM
  15009.  
  15010.  Product Version(s): 4.00 5.00 5.10
  15011.  Operating System:   MS-DOS
  15012.  Flags: ENDUSER | S_QUICKC H_MASM B_QUICKBAS B_BASCOM
  15013.  Last Modified: 25-JUL-1990    ArticleIdent: Q42830
  15014.  
  15015.  A call to Quarterdeck Office Systems has confirmed that their
  15016.  Quarterdeck Expanded Memory Manager (QEMM) driver is responsible for
  15017.  the following error message reported by several customers:
  15018.  
  15019.      Exception #13 at xxxx:xxxx
  15020.      Error code 0
  15021.      Terminate, Reboot or Continue?
  15022.  
  15023.  This message indicates that an error was detected by the Quarterdeck
  15024.  memory manager. This error is essentially the same as a general
  15025.  protection fault in OS/2 and typically indicates that a stray pointer
  15026.  is involved.
  15027.  
  15028.  The error may occur either while the program is executing or after
  15029.  execution has ended and the program is returning to DOS. A technician
  15030.  at Quarterdeck stated that they generally use CodeView to track down
  15031.  such errors, and that while the address printed in the error
  15032.  diagnostic does not necessarily indicate the precise location of the
  15033.  error, it does indicate the location at which the error was first
  15034.  detected.
  15035.  
  15036.  
  15037.  350. Near Const Data Placed in _DATA in C 5.10
  15038.  
  15039.  Product Version(s): 5.00 5.10 | 5.10
  15040.  Operating System:   MS-DOS    | OS/2
  15041.  Flags: ENDUSER |
  15042.  Last Modified: 17-MAY-1989    ArticleIdent: Q42850
  15043.  
  15044.  Question:
  15045.  
  15046.  I have a program which was originally written in Microsoft C Version
  15047.  5.00. From the combined source-object code listing, I notice that the
  15048.  near constant data items are placed in the _CONST segment of DGROUP.
  15049.  In C Version 5.10, these same data items are placed in the _DATA
  15050.  segment. Is there a reason for this, and can I specify the items to
  15051.  remain in _CONST?
  15052.  
  15053.  Response:
  15054.  
  15055.  In C 5.00, near constant data was placed in _CONST because it was
  15056.  constant and produced more easily ROMable code. Unfortunately, the /Gt
  15057.  and /ND switches would not affect it. C Version 5.10 reverted to the C
  15058.  Version 4.00 convention of putting such data in _DATA. The /Gm switch
  15059.  is provided to specify the C Version 5.00 convention instead.
  15060.  
  15061.  For more information see the Update section, Page 51, of the
  15062.  "Microsoft C 5.10 Optimizing Compiler User's Guide."
  15063.  
  15064.  
  15065.  351. Limit of 40 Files with LLIBCMT.LIB and LLIBCDLL.LIB
  15066.  
  15067.  Product Version(s): 5.10
  15068.  Operating System:   OS/2
  15069.  Flags: ENDUSER |
  15070.  Last Modified: 25-JUL-1990    ArticleIdent: Q42929
  15071.  
  15072.  Start-up source code is provided for the real- and protected-mode
  15073.  standard C run-time libraries. This code can be modified to allow more
  15074.  file handles and stream pointers to be opened by a process.
  15075.  
  15076.  This start-up code is not designed for LLIBCMT.LIB or CRTLIB.DLL.
  15077.  These are the protected-mode libraries for multithreaded applications
  15078.  and DLLs. The file and stream limits on both of these libraries are
  15079.  hard coded at 40.
  15080.  
  15081.  Handles 0, 1, and 2 are opened by C for stdin, stdout, and stderr,
  15082.  while handles 3, 7, and 8 are opened by different OS/2 subsystems.
  15083.  With these file handles taken, 34 files can be opened at once.
  15084.  
  15085.  Note: This restrictin has been removed from the C 6.0 version of these
  15086.  libraries. In fact, even with C 5.10, the open file count could be
  15087.  bumped up using DosSetMaxFH().  The problem was with the streams. In C
  15088.  6.0, the readme.doc file details how to increase the file stream count
  15089.  also.
  15090.  
  15091.  
  15092.  352. Passing Two-Dimensional Arrays between C and FORTRAN
  15093.  
  15094.  Product Version(s): 5.10   | 5.10
  15095.  Operating System:   MS-DOS | OS/2
  15096.  Flags: ENDUSER | H_FORTRAN
  15097.  Last Modified: 18-MAY-1989    ArticleIdent: Q43000
  15098.  
  15099.  When passing two-dimensional arrays from FORTRAN to C and vice versa,
  15100.  it is important to note that the indexing conventions for the two
  15101.  languages are different.
  15102.  
  15103.  C arrays are indexed row followed by column; or, the second index
  15104.  varies the quickest. However, FORTRAN is indexed just the opposite: in
  15105.  FORTRAN, two-dimensional arrays are indexed with the first indice
  15106.  varying the quickest. Thus, passing two-dimensioned arrays requires
  15107.  modification to either the C code or the FORTRAN code.
  15108.  
  15109.  For more information regarding passing arrays between C and FORTRAN,
  15110.  please see Page 127, Section 9.1.2, "Array Declaration and Indexing,"
  15111.  in the "Microsoft Mixed-Language Programming Guide for the MS-DOS
  15112.  Operating System."
  15113.  
  15114.  The following code samples define an array in a common block in
  15115.  FORTRAN, then use C to print the arrays to the screen:
  15116.  
  15117.  c     program mix_for.for
  15118.  c
  15119.  c
  15120.  c     this is to be used with mix_c.c......
  15121.  c
  15122.        subroutine test ()
  15123.        common/cblock/array(0:8,0:1)
  15124.        integer*4 i,j
  15125.  
  15126.        do 20 i = 0,8,1
  15127.          do 30 j = 0,1,1
  15128.          array(i,j) = i
  15129.        write(6,*)'the value of (',i,':',j,') is ',array(i,j)
  15130.    30  continue
  15131.    20  continue
  15132.        end
  15133.  
  15134.  /*  program mix_c.c
  15135.  
  15136.      this program is to be used with  mix_for.for......
  15137.      */
  15138.  
  15139.  #include <stdio.h>
  15140.  
  15141.  struct common_blk{
  15142.                   float array[2][9]; /* note that the subscripts
  15143.                                          of the array are inverted */
  15144.                   };
  15145.  
  15146.  extern void fortran test (void);
  15147.  
  15148.  extern struct common_blk fortran cblock;
  15149.  
  15150.  main()
  15151.  {
  15152.      int i,j;
  15153.      test();
  15154.      for(i=0;i<=8;i++)
  15155.          for(j=0;j<=1;j++)
  15156.              printf("\nthe value of %d:%d is %f"
  15157.                            ,i,j,cblock.array[j][i]);
  15158.  }
  15159.  
  15160.  
  15161.  353. Return Values for _remapallpalette and _remappalette
  15162.  
  15163.  Product Version(s): 5.10
  15164.  Operating System:   MS-DOS
  15165.  Flags: ENDUSER | S_QuickC docerr
  15166.  Last Modified: 17-MAY-1989    ArticleIdent: Q43002
  15167.  
  15168.  The function _remapallpalette returns (short) -1 when successful and
  15169.  (short) 0 on error.
  15170.  
  15171.  The function _remappalette returns (long) previous color number of the
  15172.  pixel on success and (long) -1 on error.
  15173.  
  15174.  Their return values are incorrectly stated on Page 488 in the
  15175.  "Microsoft C for the MS-DOS Operating System: Run-Time Library
  15176.  Reference" for both C Version 5.10 and QuickC Version 1.01, the C 5.10
  15177.  README.DOC, and QuickC 2.00 Advisor (on-line help screens titled
  15178.  "Help: _remapallpalette" and "Help: _remappalette).
  15179.  
  15180.  
  15181.  354. Reading Extended Keyboard Characters with C
  15182.  
  15183.  Product Version(s): 5.00 5.10
  15184.  Operating System:   MS-DOS
  15185.  Flags: ENDUSER | S_QUICKC
  15186.  Last Modified: 17-MAY-1989    ArticleIdent: Q43007
  15187.  
  15188.  Question:
  15189.  
  15190.  How do I read from the extended keyboard with the C _bios_keybrd
  15191.  routine? It does not seem to recognize the scan codes for the
  15192.  additional keys of the extended keyboard.
  15193.  
  15194.  Response:
  15195.  
  15196.  The _bios_keybrd function uses INT function 16H to access the keyboard
  15197.  services. The _bios_keybrd function is based on the original PC BIOS
  15198.  INT 16H, which does not support the extended keyboard. The BIOS for
  15199.  AT's and PS/2's has been updated to support the extended keyboard. The
  15200.  updated BIOS has three addition services: 10H reads a character from
  15201.  the extended keyboard, 11H gets the extended-keyboard status, 12H gets
  15202.  the extended-keyboard flags.
  15203.  
  15204.  To allow the C function _bios_keybrd to use these updated keyboard
  15205.  services, add the following manifest constants to the bios.h include
  15206.  file:
  15207.  
  15208.  /* manifest constants for BIOS enhanced keyboard services */
  15209.  
  15210.  #define _EXT_KEYBRD_READ         0x10  /* read character */
  15211.  #define _EXT_KEYBRD_READY        0x11  /* check if key waiting */
  15212.  /* check status of shift keys*/
  15213.  #define _EXT_KEYBRD_SHIFT_STATUS 0x12
  15214.  
  15215.  To read keys from the extended keyboard, use these new constants in
  15216.  place of the manifest constants described on Page 138 of the
  15217.  "Microsoft C for the MS-DOS Operating System: Run-Time Library
  15218.  Reference" for Version 5.10.
  15219.  
  15220.  The following program uses the enhanced services of INT function 16H
  15221.  to determine if the UP ARROW or DOWN ARROW keys on the extended
  15222.  keyboard were pressed:
  15223.  
  15224.  #include <bios.h>
  15225.  #include <stdio.h>
  15226.  
  15227.  main()
  15228.  {
  15229.          unsigned key;
  15230.  
  15231.          key = _bios_keybrd(EXT_KEYBRD_READ);
  15232.          if ( key == 0x48e0)
  15233.                  printf("up arrow key was pressed\n");
  15234.          if ( key == 0x50e0)
  15235.                  printf("down arrow key was pressed\n");
  15236.  }
  15237.  
  15238.  
  15239.  355. Switching from Reading to Writing Files Can Garble Data
  15240.  
  15241.  Product Version(s): 5.10   | 5.10
  15242.  Operating System:   MS-DOS | OS/2
  15243.  Flags: ENDUSER | s_quickc sequence locate position
  15244.  Last Modified: 17-JAN-1990    ArticleIdent: Q43072
  15245.  
  15246.  When switching from reading to writing of C Version 5.10 files, it is
  15247.  necessary to do an fsetpos, fseek, or rewind. If you do not use one of
  15248.  these library functions, the file pointer may not be updated and you
  15249.  could get some erroneous results. This also applies when switching
  15250.  from writing to reading. This is documented on Page 275 of the
  15251.  "Microsoft C Run-Time Library Reference" manual.
  15252.  
  15253.  The following program will attempt to read in the first character of a
  15254.  file and to write it out as the second character:
  15255.  
  15256.  #include <stdio.h>
  15257.  void main(void)
  15258.  {
  15259.    FILE *fp;
  15260.    char a;
  15261.  
  15262.    if (( fp = fopen("text.fil","r+")) != NULL)
  15263.    {
  15264.      fscanf(fp,"%c",a);      /* read one character */
  15265.      fprintf(fp,"%c",a);     /* write to the next location */
  15266.      fclose(fp);
  15267.    }
  15268.  }
  15269.  
  15270.  The above program will fail because there is no fseek, fsetpos, or
  15271.  rewind between the fscanf and fprintf. The following program will
  15272.  perform the desired operation:
  15273.  
  15274.  #include <stdio.h>
  15275.  void main(void)
  15276.  {
  15277.    FILE *fp;
  15278.    char a;
  15279.    fpos_t loc;     /* storage for the current location */
  15280.  
  15281.    if (( fp = fopen("text.fil","r+")) != NULL)
  15282.    {
  15283.      fscanf(fp,"%c",a);    /* read one character */
  15284.      fgetpos(fp,&loc);     /* get current file pointer pos */
  15285.      fsetpos(fp,&loc);     /* set current file pointer pos */
  15286.      fprintf(fp,"%c",a);   /* write to next location */
  15287.      fclose(fp);
  15288.    }
  15289.  }
  15290.  
  15291.  
  15292.  356. The Function fopen Accepts Filenames with Embedded Spaces
  15293.  
  15294.  Product Version(s): 5.10   | 5.10
  15295.  Operating System:   MS-DOS | OS/2
  15296.  Flags: ENDUSER | s_quickc
  15297.  Last Modified: 17-MAY-1989    ArticleIdent: Q43073
  15298.  
  15299.  The Microsoft run-time library functions fopen and open do not screen
  15300.  for invalid filenames. These functions will accept a filename string
  15301.  with an embedded space. For example, the following program will create
  15302.  the file "he llo.dat" (without the quotation marks):
  15303.  
  15304.  #include <stdio.h>
  15305.  FILE *fh;
  15306.  void main(void)  {
  15307.     fh = fopen ("he llo.dat", "w+);
  15308.  }
  15309.  
  15310.  This error is not the result of a problem with fopen or open. The
  15311.  functions fopen and open should not be expected to screen filenames.
  15312.  This activity should be handled by the program using these routines.
  15313.  Filename screening is not specified in the "Microsoft C for the MS-DOS
  15314.  Operating System: Run-Time Library Reference" manual; this applies to
  15315.  both MS-DOS and OS/2.
  15316.  
  15317.  However, the creation of this file could cause some difficulties under
  15318.  DOS. The simplest way to delete such a file would be "del *.dat"
  15319.  (without the quotation marks).
  15320.  
  15321.  
  15322.  357. C: Using the _dos_findfirst and _dosfindnext Functions
  15323.  
  15324.  Product Version(s): 5.00 5.10 | 5.10
  15325.  Operating System:   MS_DOS    | OS/2
  15326.  Flags: ENDUSER | s_quickc
  15327.  Last Modified: 17-MAY-1989    ArticleIdent: Q43144
  15328.  
  15329.  Question:
  15330.  
  15331.  Why do all my files show up in addition to the subdirectories when
  15332.  using the _dos_findfirst and _dos_findnext functions to find all the
  15333.  subdirectories in my working directory?
  15334.  
  15335.  Response:
  15336.  
  15337.  When the attribute argument to the _dos_findfirst and _dos_findnext
  15338.  functions is either _A_RDONLY, _A_HIDDEN, _A_SYSTEM, or _A_SUBDIR, the
  15339.  functions will return all normal-attribute files.  A normal-attribute
  15340.  file is any file that does not have a read-only, hidden, system, or
  15341.  directory attribute.
  15342.  
  15343.  Thus, the following function call will return either a normal file or
  15344.  a subdirectory:
  15345.  
  15346.     _dos_findfirst( "*.*", _A_SUBDIR, &c_file )
  15347.  
  15348.  To verify that the returned c_file is a subdirectory, check the
  15349.  attribute field of the c_file to determine whether the _A_SUBDIR bit
  15350.  is set. If so, then it is a subdirectory. This process may be
  15351.  accomplished by bitwise-ANDing c_file.attrib with _A_SUBDIR and
  15352.  checking for a nonzero result.
  15353.  
  15354.  The following program illustrates the use of these functions:
  15355.  
  15356.  #include <dos.h>
  15357.  #include <stdio.h>
  15358.  
  15359.  main()
  15360.  {
  15361.          struct find_t c_file;
  15362.  
  15363.          _dos_findfirst( "*.*", _A_SUBDIR, &c_file );
  15364.  
  15365.          if( c_file.attrib & _A_SUBDIR )
  15366.          printf( "Directory listing %s\n", c_file.name );
  15367.  
  15368.          while (_dos_findnext(&c_file) == 0)
  15369.              if( c_file.attrib & _A_SUBDIR )
  15370.              printf( "Directory listing %s\n", c_file.name );
  15371.  }
  15372.  
  15373.  
  15374.  358. C: How Stack Checking Is Done
  15375.  
  15376.  Product Version(s): 5.10   | 5.10
  15377.  Operating System:   MS-DOS | OS/2
  15378.  Flags: ENDUSER |
  15379.  Last Modified: 22-MAY-1989    ArticleIdent: Q43166
  15380.  
  15381.  Microsoft C does stack checking to check for stack overflow. The stack
  15382.  for an application program grows from high memory to low memory. The
  15383.  lowest memory location to which the stack can grow is determined in
  15384.  Microsoft C as follows:
  15385.  
  15386.  &end + STACKSLOP      /* in assembly: OFFSET _end + STACKSLOP */
  15387.  
  15388.  The _end symbol is created by Microsoft LINK which assigns it the
  15389.  address of the lowest memory location of the STACK segment.
  15390.  
  15391.  STACKSLOP is a manifest constant. For DOS, STACKSLOP = 256 (decimal);
  15392.  for OS/2, STACKSLOP = 512 (decimal).
  15393.  
  15394.  At runtime, the function _chkstk is called, on entry to each function,
  15395.  to check the stack. If the current value of the SP register minus the
  15396.  total size of the local variables is less than the sum of &end plus
  15397.  STACKLOP, _chkstk prints the following error message and terminates
  15398.  the program:
  15399.  
  15400.  R6000   stack overflow
  15401.  
  15402.  Otherwise, _chkstk will update the value of SP according to the total
  15403.  size of the local variables.
  15404.  
  15405.  The source code for the function _chkstk is included in the startup
  15406.  source code in the Microsoft C Optimizing Compiler Version 5.10.
  15407.  
  15408.  The value of the SP register is not updated if the stack overflow
  15409.  condition is detected.
  15410.  
  15411.  Stack checking can be manually disabled with either the compile line
  15412.  option /Gs, or with the pragma; #pragma check_stack(off). In that
  15413.  case, SP will be updated even if a stack overflow occurs.
  15414.  
  15415.  For more information on _end, query on _edata.
  15416.  
  15417.  
  15418.  359. Critical Error during Spawn Will Lose Parent
  15419.  
  15420.  Product Version(s): 5.10
  15421.  Operating System:   MS-DOS
  15422.  Flags: ENDUSER | s_quickc
  15423.  Last Modified: 17-MAY-1989    ArticleIdent: Q43537
  15424.  
  15425.  A critical error occurs when spawning another program using one of the
  15426.  C Version 5.10 run-time library's spawn functions that can prevent the
  15427.  child program from returning to the parent process. A sample program
  15428.  is shown below.
  15429.  
  15430.  This is not a problem with the run-time library, but is a limitation
  15431.  of the spawn family of functions.
  15432.  
  15433.  A workaround is to attempt to open the .EXE file before the spawn. The
  15434.  critical error will occur on the open and allow DOS and the run-time
  15435.  library to handle any problems encountered in a more elegant fashion.
  15436.  
  15437.  The following program can be used to demonstrate the situation:
  15438.  
  15439.      #include <stdio.h>
  15440.      #include <process.h>
  15441.  
  15442.      void main( void )
  15443.      {
  15444.          spawnlp( P_WAIT, "a:\\test.exe", "a:\\test.exe", NULL );
  15445.      }
  15446.  
  15447.  If Drive A is ready, TEST.EXE will be spawned correctly and return to
  15448.  the parent. However, if the drive door is open, the following prompt
  15449.  will be produced by the DOS critical error handler "Abort, Retry,
  15450.  Fail?".
  15451.  
  15452.  If the drive door is closed and "Retry" is selected, TEST.EXE will run
  15453.  but not return to the parent, hanging the system. An assembly language
  15454.  program that simply calls DOS interrupt 4B to do the same thing will
  15455.  work correctly under the same conditions.
  15456.  
  15457.  
  15458.  360. C: Cannot Bind Programs with Increased File Handles
  15459.  
  15460.  Product Version(s): 5.10   | 5.10
  15461.  Operating System:   MS-DOS | OS/2
  15462.  Flags: ENDUSER |
  15463.  Last Modified: 17-MAY-1989    ArticleIdent: Q43271
  15464.  
  15465.  Microsoft C defaults to making 20 file handles available to an
  15466.  application. This is the case for both OS/2 and DOS. This number can
  15467.  be increased by modifying the start-up source code provided with
  15468.  Optimizing C Version 5.10 and linking in the resulting OBJs. This is
  15469.  documented in the README.DOC (search for _NFILE_).
  15470.  
  15471.  However, it is not possible to bind a program that is linked to these
  15472.  modified OBJs. This is because the protect-mode start up makes a call
  15473.  to DOSSETMAXFH after being modified. This function is not FAPI (dual
  15474.  mode) and is not bindable.
  15475.  
  15476.  To give a program more than 20 file handles under both OS/2 and DOS,
  15477.  you must create separate EXEs for each environment.
  15478.  
  15479.  An attempt to bind a program that is linked with modified start up will
  15480.  produce the following error:
  15481.  
  15482.     LINK : error L2029: Unresolved externals:
  15483.  
  15484.     DOSSETMAXFH in file(s):
  15485.     BV3.OBJ(bindv3)
  15486.  
  15487.  The start-up files that must be modified to increase the number of
  15488.  available file handles are CRT0DAT.ASM and _FILE.C.
  15489.  
  15490.  
  15491.  361. Printing ASCII Characters Greater Than 127 Fails in CGA Mode
  15492.  
  15493.  Product Version(s): 5.00 5.10
  15494.  Operating System:   MS-DOS
  15495.  Flags: ENDUSER | s_quickc
  15496.  Last Modified: 17-MAY-1989    ArticleIdent: Q43272
  15497.  
  15498.  When a CGA graphics card is in any CGA graphics mode it will not
  15499.  display ASCII characters greater than 127 when Microsoft C text-output
  15500.  routines are used. Garbage characters will be displayed instead.
  15501.  
  15502.  This is expected behavior. The default character-definition table for
  15503.  CGA graphics cards contains only the first 128 ASCII characters. To
  15504.  print ASCII characters 128 to 255, a separate character-definition
  15505.  table must be set up and accessed through interrupt vector 1FH. The
  15506.  MS-DOS utility GRAFTABL leaves such a table and hooks the interrupt
  15507.  1FH vector to point to it.
  15508.  
  15509.  For more information, see Richard Wilton's book "Programmer's Guide to
  15510.  PC & PS/2 Video Systems," Page 269, which is available from Microsoft
  15511.  Press.
  15512.  
  15513.  
  15514.  362. C: Spawned Program Accessing Parent's Functions
  15515.  
  15516.  Product Version(s): 5.10   | 5.10
  15517.  Operating System:   MS-DOS | OS/2
  15518.  Flags: ENDUSER |
  15519.  Last Modified: 18-MAY-1989    ArticleIdent: Q43318
  15520.  
  15521.  It is possible for a program spawned with the P_WAIT modeflag to
  15522.  successfully call functions within its parent. The functions must be
  15523.  set up in such a way that CPU registers are preserved and the data
  15524.  segment register is loaded as necessary. It is also vitally important
  15525.  that all necessary start-up code and C run time are present whenever
  15526.  the parent functions are called.
  15527.  
  15528.  Warning: This procedure is neither recommended nor supported. This
  15529.  article is for informational purposes only.
  15530.  
  15531.  The programs below, PARENT.C and CHILD.C, demonstrate this technique.
  15532.  This method of sharing functions may be useful as a primitive form of
  15533.  overlaying when there is a need for a common set of functions to be
  15534.  accessed by a sequence of spawned child processes. The method of
  15535.  communication from the parent to the child is through command-line
  15536.  arguments. In the parent, a far pointer to the function that will be
  15537.  called is converted to a string and passed as a parameter through a
  15538.  spawn. In the child, it is then converted back into a far pointer.
  15539.  
  15540.  There are several considerations to be made when writing code of this
  15541.  nature.
  15542.  
  15543.  For any variables in the parent to be accessed, the routines to be
  15544.  called must use the _loadds keyword. Not loading DS for the called
  15545.  function results in the child's DS being used rather than the DS
  15546.  associated with the function in the parent.
  15547.  
  15548.  Even if _loadds is used, however, DS will not be equal to SS, since
  15549.  the child's stack is the one that is used and there is no mechanism in
  15550.  C for changing stacks. It is necessary to ensure that the functions
  15551.  called by the child do not blow out the child's stack.
  15552.  
  15553.  Many of the run-time library routines rely on SS equaling DS;
  15554.  therefore, one must obviously avoid those routines.
  15555.  
  15556.  Preservation of the child's state can be accomplished by using the
  15557.  _saveregs keyword. This is not necessary when calling C from C;
  15558.  however, it may be vital if C is being called from MASM.
  15559.  
  15560.  All calls must be far since the parent and child were loaded
  15561.  separately. Different memory models may be used for parent and child.
  15562.  
  15563.  This process obviously produces a general-protection fault in OS/2.
  15564.  Use dynamic link libraries to duplicate this functionality with
  15565.  greater ease, portability, and safety.
  15566.  
  15567.  The following is the parent program:
  15568.  
  15569.  /*
  15570.   *   PARENT.C
  15571.   */
  15572.  
  15573.  #include <stdio.h>
  15574.  #include <stdlib.h>
  15575.  #include <process.h>
  15576.  
  15577.  int far _saveregs _loadds foo( void );
  15578.  void main( void );
  15579.  
  15580.  int         k = 0,
  15581.              l = 0;              /* Globals to be accessed inside foo */
  15582.  
  15583.  int far _saveregs _loadds foo()
  15584.  {
  15585.      int         i,              /* Return value */
  15586.                  j;              /* Indexing */
  15587.  
  15588.      for( j = 1; j < 10; j++ )
  15589.      {
  15590.          k = k + j;
  15591.          l = k * j;
  15592.      }
  15593.      i = k + l;
  15594.      return( i );
  15595.  }
  15596.  
  15597.  void main()
  15598.  {
  15599.      int         (far _saveregs _loadds *fooaddr)();  /* foo() pointer */
  15600.      char        address[16];                         /* address to pass */
  15601.  
  15602.      printf( "Now inside parent main().\n" );
  15603.      fooaddr = foo;
  15604.      ultoa( (unsigned long)fooaddr, address, 10 );
  15605.      printf( "Address of foo(): %s\n", address );
  15606.  
  15607.      spawnlp( P_WAIT, "child.exe", "child.exe", address, NULL );
  15608.      printf( "Back inside parent main().\n" );
  15609.  }
  15610.  
  15611.  The following is the child program:
  15612.  
  15613.  /*
  15614.   *   CHILD.C
  15615.   */
  15616.  
  15617.  #include <stdio.h>
  15618.  #include <stdlib.h>
  15619.  
  15620.  void main(
  15621.      int         argc,
  15622.      char        **argv )
  15623.  {
  15624.      int         (far *fooaddr)();      /* Pointer to parent's function */
  15625.      int         i;                     /* Function return value */
  15626.  
  15627.      printf( "    Now in child.\n" );
  15628.      fooaddr = (void far *)atol( argv[1] );
  15629.      printf( "    Received: %ld\n", fooaddr );
  15630.      printf( "    Calling foo().\n" );
  15631.      i = fooaddr();
  15632.      printf( "        Result of foo(): %d\n", i );
  15633.      printf( "    Leaving child.\n" );
  15634.  }
  15635.  
  15636.  
  15637.  363. C: exec and spawn (P_OVERLAY) Will Fail When Bound
  15638.  
  15639.  Product Version(s): 5.10   | 5.10
  15640.  Operating System:   MS-DOS | OS/2
  15641.  Flags: ENDUSER | O_OS2SDK
  15642.  Last Modified: 15-JAN-1990    ArticleIdent: Q43319
  15643.  
  15644.  The Microsoft C run-time library functions exec and spawn (with a
  15645.  P_OVERLAY attribute) do not work correctly when executed in a bound
  15646.  application under DOS. This is briefly documented on Page 24 of the
  15647.  "Microsoft C for MS OS/2 and MS-DOS Operating Systems: Version 5.1
  15648.  Update" manual. The execution will fail with the program returning the
  15649.  following error message:
  15650.  
  15651.     run-time error R6006
  15652.     - bad format on exec
  15653.  
  15654.  This occurs only when the dual-mode program is running under DOS. A
  15655.  spawn with the P_WAIT attribute will work properly.
  15656.  
  15657.  Examining the DosExecPgm() API reveals that there is no option to
  15658.  overlay the currently executing program. OS/2's protection scheme does
  15659.  not support overwriting the code segment; therefore, to exec another
  15660.  program, it is necessary to actually spawn the program in a different
  15661.  area of memory and terminate the current process.
  15662.  
  15663.  To create a bound program that uses overlays, not only would a
  15664.  remapping of the FAPI function be necessary, but also a complete
  15665.  reprogramming to allow for loading over the current code segment. At
  15666.  this time, BIND does not support this.
  15667.  
  15668.  The following functions do not work properly when executed under DOS
  15669.  in a bound application:
  15670.  
  15671.     execl    execle  execlp   execlpe   execv    execve   execvp
  15672.     execvpe  spawnl  spawnl   spawnle   spawnlp  spawnlpe spawnv
  15673.     spawnve  spawnvp spawnvpe
  15674.  
  15675.  Note: The spawn functions fail only with the P_OVERLAY attribute.
  15676.  
  15677.  The following program will fail to spawn PROG.EXE from DOS:
  15678.  
  15679.  /* Program:  spawn.c                                      */
  15680.  /*                                                        */
  15681.  /* Compile and bind from OS/2 with:                       */
  15682.  /*                                                        */
  15683.  /*         cl /Lp spawn.c                                 */
  15684.  /*         bind spawn /c/lib/api.lib /c/lib/doscalls.lib  */
  15685.  
  15686.  #include <stdio.h>
  15687.  #include <process.h>
  15688.  
  15689.  void main(void)
  15690.  {
  15691.    spawnl(P_OVERLAY,"c:\\tmp\\prog.exe","prog",NULL);
  15692.  }
  15693.  
  15694.  
  15695.  364. How to Use _remappalette in EGA Modes
  15696.  
  15697.  Product Version(s): 5.10
  15698.  Operating System:   MS-DOS
  15699.  Flags: ENDUSER | s_quickc
  15700.  Last Modified: 17-MAY-1989    ArticleIdent: Q43330
  15701.  
  15702.  When attempting to remap the palette in the EGA modes, follow the
  15703.  required format to form the argument passed to the remapping
  15704.  functions. This article uses _remappalette as an example. What is said
  15705.  about lColor (see function prototype below) also applies to the
  15706.  element of the array slColors for _remapallpalette.
  15707.  
  15708.  The function prototypes are as follows:
  15709.  
  15710.  short far _remappalette (nPixel, lColor) ;
  15711.  short nPixel ;
  15712.  long lColor ;                   Color number to assign nPixel to
  15713.  
  15714.  short far _remapallpalette (slColors) ;
  15715.  long far * slColors ;           Color array
  15716.  
  15717.  lColor is a long int formed by the following four bytes:
  15718.  
  15719.      00, blue byte, green byte, red byte
  15720.  
  15721.  The four bytes are arranged from the most significant byte to the
  15722.  least significant byte (left to right). The most significant byte is
  15723.  always "0" (zero). Each of the remaining three bytes can have the
  15724.  value of either 00, 2a, 15, or 3f. (In VGA mode, each byte can take
  15725.  any value between 00 and 3f.) Combinations of different values in the
  15726.  three bytes form the complete palette of 64 colors for the EGA
  15727.  graphics modes.
  15728.  
  15729.  The manifest constants for the EGA modes are _MRES16COLOR,
  15730.  _HRES16COLOR, and _ERESCOLOR, which are used with the function
  15731.  _setvideomode.
  15732.  
  15733.  Please refer to the include file "GRAPH.H" for the default values of
  15734.  the 16 colors in an EGA mode.
  15735.  
  15736.  An algorithm is provided in this section to convert a color
  15737.  represented by an arbitrary number from 0 - 63 to the required format.
  15738.  A sample program is included that implements the algorithm.
  15739.  
  15740.  Suppose the color is represented by a byte, as follows:
  15741.  
  15742.     bit7 , bit6 , bit5 , bit4 , bit3 , bit2 , bit1 , bit0
  15743.  
  15744.  1. bit7 and bit6 can be ignored, because the byte is always less than
  15745.     64.
  15746.  
  15747.  2. The remaining bits are grouped in the following three pairs, where
  15748.     the order of the two bits in the pair is significant:
  15749.  
  15750.     bit3 , bit0 ;
  15751.     bit4 , bit1 ;
  15752.     bit5 , bit2 ;
  15753.  
  15754.  3. Each pair is mapped to 00, 2a, 15, or 3f, according to the
  15755.     following table:
  15756.  
  15757.     bitX   bitY   MappedXY
  15758.       0      0      00
  15759.       0      1      2a
  15760.       1      0      15
  15761.       1      1      3f
  15762.  
  15763.  4. Mapped30 (from pair bit3, bit0) goes to the blue byte.
  15764.     Mapped41 (from pair bit4, bit1) goes to the green byte.
  15765.     Mapped52 (from pair bit5, bit2) goes to the red byte.
  15766.  
  15767.     The order (from high to low) of the three bytes is as follows:
  15768.  
  15769.        blue byte  ,  green byte  ,  red byte
  15770.  
  15771.  5. Example:
  15772.  
  15773.     Color 43 has bit pattern 0 0 1 0 1 0 1 1. This pattern is
  15774.     transformed to three pairs : 11, 01, 10. The three pairs are mapped
  15775.     to 3f, 2a, 15. The mapped color represented in long integer format
  15776.     is 0x3f2a15.
  15777.  
  15778.  The following program uses _remappalette to remap the color "0" (which
  15779.  defaults to black) to the 64 different colors:
  15780.  
  15781.  // file : palette.c
  15782.  
  15783.  #include <stdio.h>
  15784.  #include <graph.h>
  15785.  #include <conio.h>
  15786.  
  15787.  #define NUMCOLOR        64
  15788.  #define MASK            0x0001
  15789.  
  15790.  unsigned long ConvertColNum (unsigned int) ;
  15791.  
  15792.  unsigned char ConvertArr [4] = { 0x00, 0x2a, 0x15, 0x3f } ;
  15793.  
  15794.  void main (void)
  15795.  {
  15796.  unsigned short nColor = 0 ;
  15797.  unsigned int i ;
  15798.  unsigned long lMappedColor ;
  15799.  
  15800.  if (!_setvideomode (_ERESCOLOR))
  15801.      return ;
  15802.  
  15803.  puts ("Press any key to continue ...") ;
  15804.  getch () ;
  15805.  
  15806.  for (i = 0 ; i < NUMCOLOR ; i++)
  15807.      {
  15808.      lMappedColor = ConvertColNum (i) ;
  15809.      if (_remappalette (nColor, lMappedColor) == -1L)
  15810.          puts ("\x007Mapping color failed : ") ;  // beep if fails
  15811.  
  15812.      printf ("Color number = %u, lMappedColor = %08lx\n", i,
  15813.              lMappedColor);
  15814.      if (getch () == 'q')
  15815.          break ;
  15816.      }
  15817.  
  15818.  _setvideomode (_DEFAULTMODE) ;
  15819.  }
  15820.  
  15821.  unsigned long ConvertColNum (unsigned int nOrgColor)
  15822.  {
  15823.      unsigned long lColor, lTemp ;
  15824.      int j, temp ;
  15825.  
  15826.      lColor = 0L ;
  15827.      for (j = 0 ; j < 3 ; j++)
  15828.          {
  15829.          // get the pair
  15830.          temp = ((nOrgColor >> (j + 3) & MASK) << 1 ) |
  15831.                  (nOrgColor >> j & MASK) ;
  15832.          lTemp = (unsigned long) ConvertArr [ temp ] ;
  15833.          lColor |= lTemp << ((2-j) << 3) ;      // (2-j) * 8
  15834.          }
  15835.  
  15836.      return (lColor) ;
  15837.  }
  15838.  
  15839.  
  15840.  365. Changing System Time or Date Will Temporarily Pause Clock
  15841.  
  15842.  Product Version(s): 5.10
  15843.  Operating System:   MS-DOS
  15844.  Flags: ENDUSER | s_quickc
  15845.  Last Modified: 17-MAY-1989    ArticleIdent: Q43331
  15846.  
  15847.  The system clock temporarily pauses when the time or the date is set.
  15848.  This feature prevents cases in which the date or time may need to be
  15849.  updated during the actual time change. For example, an attempt to set
  15850.  the system date exactly at midnight using _dos_setdate would not
  15851.  produce the desired effect if the system changed the date at the same
  15852.  time it was being set. Therefore, the system clock pauses.
  15853.  
  15854.  The effects of such a pause can be seen in the sample program that
  15855.  follows. If you run this program, you will find upon exit that the
  15856.  system time is the same as when the program was started.
  15857.  
  15858.  The following is the sample program:
  15859.  
  15860.  /* Note - this code takes a couple of minutes to run */
  15861.  #include <stdio.h>
  15862.  #include <dos.h>
  15863.  
  15864.  struct dosdate_t Date;
  15865.  struct dostime_t Time;
  15866.  unsigned long loop;
  15867.  
  15868.  void main(void)  {
  15869.     _dos_getdate(&Date);       /* Show time when starting */
  15870.     _dos_gettime(&Time);
  15871.     printf ("Today's date is %d-%d-%d\n", Date.month, Date.day,
  15872.             Date.year);
  15873.     printf ("Start time = %d:%d\n", Time.hour, Time.minute);
  15874.  
  15875.     Date.year = 1988;
  15876.     for (loop = 1; loop <= 200000; loop++) {
  15877.        _dos_setdate(&Date);
  15878.     }
  15879.  
  15880.     _dos_getdate(&Date);       /* Show time after loop */
  15881.     _dos_gettime(&Time);
  15882.     printf ("Date is now %d-%d-%d\n", Date.month, Date.day, Date.year);
  15883.     printf ("End time = %d:%d\n", Time.hour, Time.minute);
  15884.  }
  15885.  
  15886.  
  15887.  
  15888.  366. Handling Floating-Point Errors in C
  15889.  
  15890.  Product Version(s): 5.00 5.10 | 5.10
  15891.  Operating System:   MS-DOS    | OS/2
  15892.  Flags: ENDUSER |
  15893.  Last Modified: 17-MAY-1989    ArticleIdent: Q43391
  15894.  
  15895.  You can set up a floating-point error-handling routine by using the
  15896.  signal() function. Do not use the return() function to return to the
  15897.  calling process. If return() is used, the floating-point state is left
  15898.  undefined.
  15899.  
  15900.  Instead, use the function setjmp() to save the stack environment
  15901.  before each section of the calling process code that may potentially
  15902.  generate a floating-point error. In the error handler, use _fpreset()
  15903.  to reinitialize the floating-point package and longjmp() to return to
  15904.  the calling process.
  15905.  
  15906.  The sample program on Page 280 of the "Microsoft C Run-time Library
  15907.  Reference" demonstrates the use of setjmp(), _fpreset(), and longjmp()
  15908.  to handle a floating-point error.
  15909.  
  15910.  The function setjmp() saves the environment (bp, si, di, sp, and ds
  15911.  registers) and return address in a buffer. The buffer is used by
  15912.  longjmp() to restore the environment.
  15913.  
  15914.  
  15915.  367. C: Clarification of the "g" Format Specifier
  15916.  
  15917.  Product Version(s): 5.00 5.10 | 5.00 5.10
  15918.  Operating System:   MS-DOS    | OS/2
  15919.  Flags: ENDUSER | s_quickc
  15920.  Last Modified: 17-MAY-1989    ArticleIdent: Q43392
  15921.  
  15922.  The output format resulting from the printf() format specifier "g"
  15923.  does not exactly match the output format resulting from either format
  15924.  specifier "e" or "f." Page 459 of the "Microsoft C Run-Time Library
  15925.  Reference" states that "g" will use either the "f" or "e" format,
  15926.  whichever is more compact.
  15927.  
  15928.  The precision value is interpreted differently in "g" format than in
  15929.  "f" format. Table R.3 on Pages 461-2 states the difference. The
  15930.  precision for "f" specifies the number of digits after the decimal
  15931.  point. The precision for "g" specifies the maximum number of
  15932.  significant digits printed.
  15933.  
  15934.  The following example demonstrates the difference:
  15935.  
  15936.  #include <stdio.h>
  15937.  
  15938.  void main (void)
  15939.  {
  15940.    printf ("%.4g\n", 4.0/3.0);    /* Outputs:  1.333  */
  15941.    printf ("%.4f\n", 4.0/3.0);    /* Outputs:  1.3333 */
  15942.  }
  15943.  
  15944.  The results of the above program are correct.
  15945.  
  15946.  
  15947.  368. C: _bios_timeofday Documentation Error
  15948.  
  15949.  Product Version(s): 5.00 5.10 | 5.00 5.10
  15950.  Operating System:   MS-DOS    | OS/2
  15951.  Flags: ENDUSER | docerr
  15952.  Last Modified: 14-APR-1989    ArticleIdent: Q43396
  15953.  
  15954.  On Page 146 of the "Microsoft C 5.1 Optimizing Compiler Run-Time
  15955.  Library Reference" manual and the "Microsoft QuickC Run-Time Library
  15956.  Reference" manual, the second parameter of _bios_timeofday is
  15957.  incorrectly stated as a long integer, as follows:
  15958.  
  15959.     long timeval;
  15960.  
  15961.  The corrected declaration is a pointer to a long integer, as follows:
  15962.  
  15963.     long *timeval;
  15964.  
  15965.  
  15966.  369. Incorrect Reference to Preprocessor Directives in User's Guide
  15967.  
  15968.  Product Version(s): 5.00 5.10 | 5.10
  15969.  Operating System:   MS-DOS    | OS/2
  15970.  Flags: ENDUSER | docerr
  15971.  Last Modified: 14-APR-1989    ArticleIdent: Q43398
  15972.  
  15973.  Section 3.3.9 on Page 75 of the "Microsoft C 5.1 Optimizing Compiler
  15974.  Users' Guide" has a documentation error at the bottom of the second
  15975.  paragraph.
  15976.  
  15977.  The paragraph refers to Section 8 of the "Microsoft C Quick Reference
  15978.  Guide"; however, Section 8 does not exist. The actual location of the
  15979.  information is in Part 2 on Pages 30-32 of the Quick Reference Guide.
  15980.  This section contains a listing of the preprocessor directives.
  15981.  
  15982.  
  15983.  370. How to Test for an Error When Using _bios_serialcom Service
  15984.  
  15985.  Product Version(s): 5.00 5.10
  15986.  Operating System:   MS-DOS
  15987.  Flags: ENDUSER | s_quickc docerr
  15988.  Last Modified: 14-APR-1989    ArticleIdent: Q43401
  15989.  
  15990.  Problem:
  15991.  
  15992.  I am using the _COM_RECEIVE function of _bios_serialcom to read data
  15993.  from a communications port. How do I determine if an error has
  15994.  occurred?
  15995.  
  15996.  Response:
  15997.  
  15998.  Referring to the table on Page 144, Page 145 of the "Microsoft
  15999.  Optimizing C Run-Time Library Reference" and the "Microsoft QuickC
  16000.  Run-Time Library Reference" states the following:
  16001.  
  16002.     If an error occurs, at least one of the high-order bits will be
  16003.     set.
  16004.  
  16005.  While this is correct, it is misleading. It is true that at least one
  16006.  of the high-order bits will be set if an error occurs. However, it is
  16007.  not true that if ANY high-order bit is set, an error has occurred. An
  16008.  error has occurred if, and only if, any of the following four bits are
  16009.  set:
  16010.  
  16011.     Bit     Meaning if Set
  16012.  
  16013.     15      Timed out
  16014.     11      Framing error
  16015.     10      Parity error
  16016.      9      Overrun error
  16017.  
  16018.  The sentence quoted above would be more accurate if it read as
  16019.  follows:
  16020.  
  16021.     If an error occurs, any of bits 9, 10, 11, or 15 will be set.
  16022.  
  16023.  This information is explained on Page 431 of "Advanced MS-DOS" by
  16024.  Ray Duncan.
  16025.  
  16026.  
  16027.  371. The Storage of Environment Variables
  16028.  
  16029.  Product Version(s): 5.10   | 5.10
  16030.  Operating System:   MS-DOS | OS/2
  16031.  Flags: ENDUSER | S_QuickC
  16032.  Last Modified: 17-MAY-1989    ArticleIdent: Q43428
  16033.  
  16034.  Question:
  16035.  
  16036.  How can I find out where the environment variables (PATH, LIB, etc.)
  16037.  are being stored?
  16038.  
  16039.  Response:
  16040.  
  16041.  The environment variables are stored in the near heap, which is part
  16042.  of DGROUP. The ENVIRON variable is an array of pointers to the strings
  16043.  that constitute the process environment. The C start-up code takes the
  16044.  environment information and initializes the ENVIRON variable to point
  16045.  to the environment table. The function getenv() uses the ENVIRON
  16046.  variable to access the environment table. ENVIRON can be used to
  16047.  obtain the environment table address directly.
  16048.  
  16049.  The following program will print out the address of the beginning of
  16050.  the environment table and the PATH environment variable:
  16051.  
  16052.  #include <stdlib.h>
  16053.  #include <stdio.h>
  16054.  
  16055.  char *path;
  16056.  
  16057.  void main (void)
  16058.  {
  16059.    path = getenv( "PATH" );
  16060.    printf( "path: %s\nenviron: %x\n", path, environ );
  16061.  }
  16062.  
  16063.  
  16064.  372. Why _setvideomode() May Fail to Set Some Modes
  16065.  
  16066.  Product Version(s): 5.00 5.10
  16067.  Operating System:   MS-DOS
  16068.  Flags: ENDUSER | S_QUICKC setvideomode _setvideomode
  16069.  Last Modified: 25-MAY-1989    ArticleIdent: Q43587
  16070.  
  16071.  The following are possible reasons that _setvideomode() might fail
  16072.  when attempting to set a video mode:
  16073.  
  16074.  1. Some of the older IBM EGA (enhanced graphics adapter) cards only
  16075.     have 64K of video memory. As such, they cannot display the
  16076.     640 x 350 16 (_ERES16COLOR) color EGA mode. However,
  16077.     lower-resolution modes may work correctly because they don't
  16078.     require that much memory.
  16079.  
  16080.  2. There are EGA cards that have dip-switch settings to set the card
  16081.     into high- or low-resolution modes. Some BIOS ignore these dip
  16082.     switches and set the mode to high resolution. However, the
  16083.     _setvideomode() function does its own checking and may honor the
  16084.     dip-switch settings depending on the particular card. Setting the
  16085.     dip switches properly for the high-resolution modes should resolve
  16086.     the problem.
  16087.  
  16088.  3. The video card may not support the requested mode. If the card does
  16089.     not support the mode, then _setvideomode() cannot set it into that
  16090.     mode.
  16091.  
  16092.  4. Many VGA cards have non-standard extended modes that are unique to
  16093.     those cards. _setvideomode() supports only standard video modes
  16094.     and, thus, will not recognize the extended modes.
  16095.  
  16096.  
  16097.  373. C: Loop Optimization Causes Internal Compiler Error
  16098.  
  16099.  Product Version(s): 5.10   | 5.10
  16100.  Operating System:   MS-DOS | OS/2
  16101.  Flags: ENDUSER |
  16102.  Last Modified: 26-SEP-1989    ArticleIdent: Q43700
  16103.  
  16104.  The two programs shown below demonstrate the following internal
  16105.  compiler error. The error occurs in the Microsoft C Optimizing
  16106.  Compiler Version 5.10, when compiled with loop and alias relaxation
  16107.  optimization enabled, and either the compact or large-memory models.
  16108.  
  16109.      fatal error C1001 : Internal Compiler Error
  16110.         (compiler file '@(#)regMD.c:1.117', line 1861)
  16111.         Contact Microsoft Technical Support
  16112.  
  16113.  An easy workaround is to not use the /Oal combination, or use a
  16114.  different memory model.
  16115.  
  16116.  The first program is as follows:
  16117.  
  16118.  int flags = 0;                         /* change to int j, flags = 0 */
  16119.  void main(int argc, char *argv[])
  16120.  {
  16121.      int i,j;                           /* change to int i; */
  16122.      for (i=1; i<argc; i++)
  16123.          switch(argv[i][0]) {
  16124.              case '-':
  16125.                  for (j=1; argv[i][j]; j++)
  16126.                      switch (argv[i][j]) {
  16127.                          case 'a' : flags |= 0x1; break;
  16128.                          case 'b' : flags |= 0x2; break;
  16129.                          case 'c' : flags |= 0x4; break;
  16130.                          case 'd' : case '?': default: flags = 0x8; break;
  16131.                      }
  16132.         }
  16133.  }
  16134.  
  16135.  To work around this problem, move the declaration of "j" outside of
  16136.  main().
  16137.  
  16138.  The second program is as follows:
  16139.  
  16140.  typedef struct  LINE {
  16141.          short   l_used;
  16142.          char    l_text[1];
  16143.  }       LINE;
  16144.  
  16145.  typedef struct  WINDOW {
  16146.          LINE *w_dotp;
  16147.  }       WINDOW;
  16148.  
  16149.  extern  WINDOW  *curwp;
  16150.  
  16151.  void main()
  16152.  {
  16153.          int    nicol;
  16154.          int    c;
  16155.          int    i;
  16156.  
  16157.          for (i=0; i< curwp->w_dotp->l_used; ++i) {
  16158.                  c = curwp->w_dotp->l_text[i]&0xFF;
  16159.                  if (c!=' ' && c!='\t')
  16160.                          break;
  16161.                  if (c == '\t')
  16162.                          nicol |= 0x07;
  16163.                  ++nicol;
  16164.          }
  16165.  }
  16166.  
  16167.  You can work around this problem by adding a new variable of type
  16168.  pointer to WINDOW and then using this pointer in the assignment to the
  16169.  variable "c". For example, you can change the for loop in the code to
  16170.  appear as follows:
  16171.  
  16172.          for (i=0; i< curwp->w_dotp->l_used; ++i) {
  16173.                WINDOW *foo1;
  16174.                  foo1 = curwp;
  16175.                  c = foo1->w_dotp->l_text[i]&0xFF;
  16176.  
  16177.                  if (c!=' ' && c!='\t')
  16178.                          break;
  16179.                  if (c == '\t')
  16180.                          nicol |= 0x07;
  16181.                  ++nicol;
  16182.  
  16183.  Microsoft is researching this problem and will post new information as
  16184.  it becomes available.
  16185.  
  16186.  
  16187.  374. C: srand() Sample Program Does Not Print Out the Array Values
  16188.  
  16189.  Product Version(s): 5.00 5.10 | 5.10
  16190.  Operating System:   MS-DOS    | OS/2
  16191.  Flags: ENDUSER | DOCERR S_QuickC
  16192.  Last Modified: 22-MAY-1989    ArticleIdent: Q43808
  16193.  
  16194.  In the following manuals, the sample program given for the function
  16195.  srand() implies that it will print out random values for each of the
  16196.  array elements. Although the array is filled with random values, these
  16197.  values are not printed because the "for" loop is implemented
  16198.  incorrectly. This example is given in both the "Microsoft C for the
  16199.  MS-DOS Operating System Run-Time Library Reference" manual for
  16200.  Versions 5.00 and 5.10, and the "Microsoft QuickC Run-Time Library
  16201.  Reference" manual for Versions 1.00 and 1.10.
  16202.  
  16203.  The following source code fragment is excerpted from the sample
  16204.  program found in the "Microsoft QuickC Run-Time Library Reference"
  16205.  manual on Page 564.
  16206.  
  16207.      srand(17);
  16208.      for (x = 0; x < 20; ranvals[x++] = rand())
  16209.        printf("Iteration %d, ranvals[%d] =%d\n",x+1, x, ranvals[x]);
  16210.  
  16211.  If you execute the program as written, it produces a list of all zeros
  16212.  instead of a list of the random numbers being put into the array. To
  16213.  understand why this is so, the definition of a for loop must be
  16214.  considered. The for loop defined by Kernighan and Ritchie is as
  16215.  follows:
  16216.  
  16217.      for (expr1, expr2, expr3)
  16218.          statement;
  16219.  
  16220.      is equivalent to:
  16221.  
  16222.      expr1;
  16223.      while (expr2)
  16224.         {
  16225.         statement;
  16226.         expr3;
  16227.         }
  16228.  
  16229.  If the above sample program is substituted into this definition, then
  16230.  the program reads as follows:
  16231.  
  16232.      srand(17);
  16233.      x = 0;
  16234.      while (x < 20)
  16235.         {
  16236.         printf("Iteration %d, ranvals[%d] =%d\n",x+1,x,ranvals[x]);
  16237.         ranvals[x++] = rand();
  16238.         }
  16239.  
  16240.  This program obviously prints the array elements one step before they
  16241.  are initialized, which is why the sample program prints out all zeros
  16242.  instead of the desired random numbers.
  16243.  
  16244.  To display the correct results, you must take the call to  the
  16245.  function rand() out of expr3 of the for statement. This can be
  16246.  accomplished as follows:
  16247.  
  16248.      srand(17);
  16249.      for (x = 0; x < 20; x++)
  16250.         {
  16251.         ranvals[x] = rand();
  16252.         printf("Iteration %d, ranvals[%d] =%d\n",x+1, x, ranvals[x]);
  16253.         }
  16254.  
  16255.  
  16256.  375. Casting a Pointer to a Type Equivalent to a Multidimensional
  16257.  
  16258.  Product Version(s): 5.10   | 5.10
  16259.  Operating System:   MS-DOS | OS/2
  16260.  Flags: ENDUSER | s_quickc
  16261.  Last Modified: 17-MAY-1989    ArticleIdent: Q43703
  16262.  
  16263.  In some situations you may need to cast a pointer or an address to a
  16264.  type that is equivalent to a multidimensional array. The following
  16265.  example demonstrates such a situation:
  16266.  
  16267.      typedef char Arr2Dim [][20] ;
  16268.      void foo (Arr2Dim) ;
  16269.      char * ptr ;
  16270.      ...
  16271.      void main (void)
  16272.      {
  16273.          ...
  16274.          foo ( (Arr2Dim) ptr ) ;  /* illegal */
  16275.          ...
  16276.      }
  16277.  
  16278.  Casting the variable "ptr" to the array type "Arr2Dim" is illegal. The
  16279.  Microsoft C Compiler displays the following error message:
  16280.  
  16281.     error C2067: cast to array type is illegal
  16282.  
  16283.  The correct procedure is to cast the pointer "ptr" to a pointer type
  16284.  equivalent to the array type Arr2Dim. This pointer type can be defined
  16285.  as follows:
  16286.  
  16287.     typedef char (*Ptr2Dim) [20] ;
  16288.  
  16289.  Casting "ptr" to the type of "Ptr2Dim", as follows, is legal and
  16290.  produces no warning messages when compiled at warning level 3:
  16291.  
  16292.     foo ( (Ptr2Dim) ptr ) ;
  16293.  
  16294.  The address (or pointer) passed to the function will be used
  16295.  correctly.
  16296.  
  16297.  A similar solution could be applied to the problem of dynamically
  16298.  allocating a multidimensional array. For example, the following code
  16299.  fragment will allocate a memory block, which can be used as a 10 x 20
  16300.  x 30 three-dimensional array:
  16301.  
  16302.      typedef char (*Ptr3Dim) [20][30] ;
  16303.      Ptr3Dim ptr3arr ;
  16304.      ...
  16305.      void main (void)
  16306.      {
  16307.          ...
  16308.          ptr3arr = (Ptr3Dim) malloc (10 * sizeof(char) * 20 * 30) ;
  16309.          ...
  16310.      }
  16311.  
  16312.  After the allocation, "ptr2arr" can be used as a three-dimensional
  16313.  array, as follows, provided i, j, and k are integers within the proper
  16314.  range:
  16315.  
  16316.     ptr2arr [i][j][k] = 'a' ;
  16317.  
  16318.  
  16319.  376. Changes in scanf() and printf() for Long Types in C
  16320.  
  16321.  Product Version(s): 5.10   | 5.10
  16322.  Operating System:   MS-DOS | OS/2
  16323.  Flags: ENDUSER | S_QuickC
  16324.  Last Modified: 19-SEP-1989    ArticleIdent: Q43809
  16325.  
  16326.  As of Version 5.10 of the Microsoft C Optimizing Compiler and Version
  16327.  1.00 of the QuickC compiler, the scanf() and printf() functions no
  16328.  longer support the uppercase D, O, and I type characters, which
  16329.  represented long-integer fields.
  16330.  
  16331.  Current versions of Microsoft C compilers precede the type characters
  16332.  in the format portion of the printf() and scanf() functions with an
  16333.  "l"  (lowercase letter "l") to specify long-type fields.
  16334.  
  16335.  The uppercase "X" format specifier also has been changed; it now
  16336.  specifies that uppercase letters are to be used when displaying
  16337.  hexadecimal numbers in a printf() statement.
  16338.  
  16339.  The following code fragment reads an integer into a variable and then
  16340.  displays the value of the variable:
  16341.  
  16342.  int i;
  16343.  scanf( "%d", &i );
  16344.  printf( "%d", i );
  16345.  
  16346.  The following code fragment accepts and displays the value of a long
  16347.  integer variable:
  16348.  
  16349.  long i;
  16350.  scanf( "%ld", &i );
  16351.  printf( "%ld", i );
  16352.  
  16353.  
  16354.  377. C: PUSH CS Caused by Far Call Translation
  16355.  
  16356.  Product Version(s): 5.00 5.10 | 5.10
  16357.  Operating System:   MS-DOS    | OS/2
  16358.  Flags: ENDUSER |
  16359.  Last Modified: 22-MAY-1989    ArticleIdent: Q43810
  16360.  
  16361.  Question:
  16362.  
  16363.  When I look at an assembly listing generated by the Microsoft C
  16364.  Version 5.10 Optimizing Compiler, I notice that the compiler produced
  16365.  PUSH CS instructions. Should the compiler be generating PUSH CS
  16366.  instructions?
  16367.  
  16368.  Response:
  16369.  
  16370.  One of the optimizations made by the Microsoft C 5.10 compiler is Far
  16371.  Call Translation. Far Call Translation optimization results in
  16372.  slightly faster code and smaller executable files.
  16373.  
  16374.  The compiler normally generates far calls and corresponding far
  16375.  returns for large and medium-memory-model programs. Far Call
  16376.  Translation is performed if optimizations are enabled and a call is
  16377.  being made from one function to another in the same source file. The
  16378.  usual CALL FAR LABEL is replaced with the following instruction
  16379.  sequence:
  16380.  
  16381.          PUSH CS
  16382.          CALL NEAR LABEL
  16383.  
  16384.  The called function is in the same code segment because it is located
  16385.  in the same source file, so a near call is possible in this case. The
  16386.  PUSH CS instruction allows the far return from the called function to
  16387.  retrieve CS from the stack and return to the correct location.
  16388.  
  16389.  
  16390.  378. Fscanf() and White-Space Characters
  16391.  
  16392.  Product Version(s): 5.00 5.10  |  5.10
  16393.  Operating System:   MS-DOS     |  OS/2
  16394.  Flags: ENDUSER |
  16395.  Last Modified: 30-NOV-1989    ArticleIdent: Q50116
  16396.  
  16397.  Problem:
  16398.  
  16399.  I try to read one integer on a line from a data file and then advance
  16400.  the file pointer to the next line using the following:
  16401.  
  16402.      fscanf("%d\n", &INT);
  16403.  
  16404.  However, I am unable to do this. The file pointer seems to jump to the
  16405.  next character in the data file, wherever it may be, instead of
  16406.  stopping at the first position of the next line.
  16407.  
  16408.  Response:
  16409.  
  16410.  According to the "Microsoft C for the MS-DOS Operating System Run-time
  16411.  Library Reference," Page 501:
  16412.  
  16413.     A white-space character (in the format string) causes scanf to
  16414.     read, but not store, all consecutive white-space characters in the
  16415.     input up to the next non-white-space character. One white-space
  16416.     character in the format matches any number (including 0) and
  16417.     combination of white-space characters in the input.
  16418.  
  16419.  In other words, because you have white space in your format specifier,
  16420.  "\n", after the %d, fscanf() eats up all white space AFTER the
  16421.  integer, including newline until the first nonwhite-space character is
  16422.  found.
  16423.  
  16424.  The following are possible workarounds:
  16425.  
  16426.  1. Use the following fscanf() statement:
  16427.  
  16428.        fscanf("%d[^\n]%*c}, &INT)
  16429.  
  16430.     This tells fscanf() to read an integer and then read UNTIL it finds
  16431.     the "\n". At that point, it is necessary to read in the \n. The
  16432.     "%*c" reads, but does not store, one character.
  16433.  
  16434.  2. Use fgets() to read in the line and then use sscanf to get the
  16435.     value, as follows:
  16436.  
  16437.        fgets( line, MAX_LINE_SIZE, stream );
  16438.              sscanf( line, "%d", &INT);
  16439.  
  16440.  
  16441.  379. Determining the Memory Model for Conditional Compilation
  16442.  
  16443.  Product Version(s): 5.10   | 5.10
  16444.  Operating System:   MS-DOS | OS/2
  16445.  Flags: ENDUSER | s_QuickC
  16446.  Last Modified: 25-JUL-1989    ArticleIdent: Q44386
  16447.  
  16448.  There is a predefined identifier that can be used to allow the
  16449.  preprocessor to determine which memory model has been chosen for the
  16450.  current compilation. The identifier is M_I86?M, where "?" is an
  16451.  identifier for one of the following five memory models:
  16452.  
  16453.     S = Small
  16454.     M = Medium
  16455.     L = Large
  16456.     C = Compact
  16457.     H = Huge
  16458.  
  16459.  This identifier can be used with a preprocessor command to produce
  16460.  conditional compilation dependent upon the memory model. An example of
  16461.  its use is shown below. For more information, refer to the include
  16462.  file MALLOC.H, which uses the identifier to determine which variant of
  16463.  the memory allocation function "malloc" should be used in the current
  16464.  compilation.
  16465.  
  16466.  Code Example
  16467.  ------------
  16468.  
  16469.  /*
  16470.   *
  16471.   * This example demonstrates how to use the C compiler M_I86?M values.
  16472.   * It also shows other various preprocessor components. The
  16473.   * memory model is displayed using the message() pragma. If the memory
  16474.   * model is not recognized by the program, the compilation terminates
  16475.   * using the #error preprocessor directive. The identifier _MEMORY_MODEL_
  16476.   * has been chosen arbitrarily, and has no special value to the C compiler.
  16477.   *
  16478.   */
  16479.  
  16480.  #include <stdio.h>
  16481.  
  16482.  #if defined (M_I86CM)
  16483.      #define _MEMORY_MODEL_ "compact"
  16484.  #elif defined (M_I86SM)
  16485.      #define _MEMORY_MODEL_ "small"
  16486.  #elif defined (M_I86MM)
  16487.      #define _MEMORY_MODEL_ "medium"
  16488.  #elif defined (M_I86LM)
  16489.      #define _MEMORY_MODEL_ "large"
  16490.  #elif defined (M_I86HM)
  16491.      #define _MEMORY_MODEL_ "huge"
  16492.  #else
  16493.      #error "ERROR: unknown memory model!!"
  16494.      #define _MEMORY_MODEL_ "**UNKNOWN**"
  16495.  #endif
  16496.  
  16497.  #pragma message ("Using the " _MEMORY_MODEL_ " memory model...")
  16498.  
  16499.  void main(void);
  16500.  
  16501.  void main(void)
  16502.  {
  16503.     printf("hello, world\n");
  16504.  }
  16505.  
  16506.  
  16507.  380. C: Finding the Length of Double Precision Decimals
  16508.  
  16509.  Product Version(s): 5.10   | 5.10
  16510.  Operating System:   MS-DOS | OS/2
  16511.  Flags: ENDUSER | SR# G890424-17022 s_quickc
  16512.  Last Modified: 22-MAY-1989    ArticleIdent: Q43913
  16513.  
  16514.  Question:
  16515.  
  16516.  Is there a straightforward way to determine how many decimal digits
  16517.  are required to fully represent the integer and fractional portions of
  16518.  a double floating-point number?
  16519.  
  16520.  Response:
  16521.  
  16522.  The most straightforward method is to convert the double to a string,
  16523.  locate the decimal point, and then calculate the length of the
  16524.  substrings before and after it.
  16525.  
  16526.  The following example demonstrates the technique:
  16527.  
  16528.          #include <stdio.h>
  16529.          #include <string.h>
  16530.          #include <ctypes.h>
  16531.  
  16532.          char str[30];
  16533.          double stuff;
  16534.          int dec_pos, places_after, places_before;
  16535.  
  16536.          ...
  16537.  
  16538.          sprintf(str, "%f", stuff);
  16539.          dec_pos = strcspn( str, "." );
  16540.          places_after = strlen( str ) - dec_pos - 1;
  16541.          places_before = dec_pos - !isdigit( str[0] );
  16542.  
  16543.  The strcspn function returns the position in str at which "." is
  16544.  found. The isdigit() function accounts for the presence or absence of
  16545.  a minus or plus sign. The sequence of steps in the string "-1253.356"
  16546.  results in the following values:
  16547.  
  16548.      dec_pos == 5
  16549.      places_after == (9 - 5 - 1) == 3
  16550.      places_before == (5 - 1) == 4
  16551.  
  16552.  
  16553.  381. C: Text Modes Don't Return Pixel Information
  16554.  
  16555.  Product Version(s): 5.10
  16556.  Operating System:   MS-DOS
  16557.  Flags: ENDUSER | s_quickc
  16558.  Last Modified: 11-JAN-1990    ArticleIdent: Q43914
  16559.  
  16560.  After a call to _getvideoconfig () from text modes, the structure
  16561.  videoconfig contains zero (0) for numxpixels, numypixels, and
  16562.  bitsperpixel. This is expected behavior because only the graphics
  16563.  modes return pixel information.
  16564.  
  16565.  Both text and graphics modes return information about the number of
  16566.  text columns and rows.
  16567.  
  16568.  The following example demonstrates the absence of pixel information
  16569.  in text modes. The name of each text mode begins with "_TEXT."
  16570.  
  16571.  #include stdio.h
  16572.  #include graph.h
  16573.  
  16574.  struct videoconfig vc;  /* variable vc of type videoconfig */
  16575.  
  16576.  /* define an array of video modes and mode names
  16577.     since the numbers are not continuous */
  16578.  
  16579.  int modes[12] = {_TEXTBW40, _TEXTC40, _TEXTBW80, _TEXTC80,
  16580.      _MRES4COLOR, _MRESNOCOLOR, _HRESBW, _TEXTMONO,
  16581.      _MRES16COLOR, _HRES16COLOR, _ERESNOCOLOR, _ERESCOLOR};
  16582.  
  16583.  char *modenames[] = {"TEXTBW40", "TEXTC40", "TEXTBW80",
  16584.                        "TEXTC80", "MRES4COLOR", "MRESNOCOLOR",
  16585.                        "HRESBW", "TEXTMONO", "MRES16COLOR",
  16586.                        "HRES16COLOR", "ERESNOCOLOR", "ERESCOLOR"};s0
  16587.  main()
  16588.  {
  16589.  
  16590.     int i;
  16591.     /* test all video modes */
  16592.     for (i=0; i<= 11; i++) {
  16593.         _setvideomode (modes[i]);
  16594.         _getvideoconfig (&vc);
  16595.         printf ("\n video mode: \t%s\n",modenames[i]);
  16596.         printf (" x pixels: \t%d\n",vc.numxpixels);
  16597.         printf (" y pixels: \t%d\n",vc.numypixels);
  16598.         printf (" text columns: \t%d\n",vc.numtextcols);
  16599.         printf (" text rows: \t%d\n",vc.numtextrows);
  16600.         printf (" # of colors: \t%d\n",vc.numcolors);
  16601.         printf (" bits/pixel: \t%d\n",vc.bitsperpixel);
  16602.         printf (" video pages: \t%d\n",vc.numvideopages);
  16603.         printf (" Hit return for next video mode");
  16604.         getchar();
  16605.         _clearscreen (_GCLEARSCREEN);
  16606.     }
  16607.     _setvideomode (_DEFAULTMODE);
  16608.  }
  16609.  
  16610.  The definition of structure videoconfig and the arguments to
  16611.  _setvideomode() are contained in the include file graph.h. The
  16612.  arguments for _setvideomode() are also present on Page 539 of the
  16613.  "Microsoft C for the MS-DOS Operating System: Run-Time Library
  16614.  Reference."
  16615.  
  16616.  
  16617.  382. qsort(): Parameters to the Compare Function
  16618.  
  16619.  Product Version(s): 5.10   | 5.10
  16620.  Operating System:   MS-DOS | OS/2
  16621.  Flags: ENDUSER | s_quickc
  16622.  Last Modified: 22-MAY-1989    ArticleIdent: Q43971
  16623.  
  16624.  When you define or prototype a comparison function for the run-time
  16625.  library function qsort(), the formal parameters should be of type
  16626.  "pointer to the type of the array element." This is because qsort()
  16627.  passes the addresses of the array elements to the comparison function.
  16628.  
  16629.  If the declaration of the array to be sorted is
  16630.  
  16631.     ELEMENT_TYPE arr[10] ;
  16632.  
  16633.  where ELEMENT_TYPE is the type of the array elements, then the
  16634.  function for comparison should be prototyped as follows:
  16635.  
  16636.     int comp( ELEMENT_TYPE *, ELEMENT_TYPE * ) ;
  16637.  
  16638.  If arr is declared instead as an array of pointers to structure foo,
  16639.  then the declaration and prototype should be as follows:
  16640.  
  16641.     struct foo * arr[10] ;
  16642.     int comp( struct foo **, struct foo ** ) ;
  16643.  
  16644.  
  16645.  383. How to Flush the Keyboard Typeahead Buffer
  16646.  
  16647.  Product Version(s): 5.10
  16648.  Operating System:   MS-DOS
  16649.  Flags: ENDUSER |
  16650.  Last Modified: 22-MAY-1989    ArticleIdent: Q43993
  16651.  
  16652.  To flush the BIOS keyboard typeahead buffer, the DOS function 0xC may
  16653.  be used. This function clears the keyboard typeahead buffer and then
  16654.  invokes a reading function specified in the AL register. The AL
  16655.  register can be 0x01, 0x06, 0x07, 0x08, or 0x0A to specify a valid
  16656.  reading function. If you do not intend to read after flushing the
  16657.  buffer, you may specify an invalid number in AL.
  16658.  
  16659.  Another method of flushing BIOS's buffer is to call the console I/O
  16660.  function getch() until the function kbhit() becomes false. This
  16661.  method is demonstrated in the program below and has the advantage of
  16662.  being usable under OS/2 as well as DOS.
  16663.  
  16664.  The buffer implemented by the C run-time functions for the stream
  16665.  "stdin" is different from the BIOS keyboard typeahead buffer. To clear
  16666.  the buffer for stdin, use the function fflush(). However, this method
  16667.  will not flush BIOS's buffer. To be totally flushed, you must both
  16668.  flush BIOS's buffer as described above in this article AND call fflush
  16669.  for stdin.
  16670.  
  16671.  The following sample program is provided for demonstration:
  16672.  
  16673.  // sample program
  16674.  #include <stdio.h>
  16675.  #include <time.h>
  16676.  #include <conio.h>
  16677.  #include <dos.h>
  16678.  
  16679.  void main (void)
  16680.  {
  16681.  time_t start, work ;
  16682.  char str [50] ;
  16683.  
  16684.  puts ("type for getchar(). Go to stdin's buffer.") ;
  16685.  // user can type more than one character and an Enter.
  16686.  getchar () ;
  16687.  
  16688.  puts ("Type fast, 5 seconds. Go to BIOS buffer.") ;
  16689.  // user can type anything including multiple Enters.
  16690.  time (&start) ;
  16691.  work = start ;
  16692.  while ( (work - start) < 5 ) time (&work) ;
  16693.  
  16694.  bdos (0xC, 0, 0) ;       // clear BIOS keyboard buffer
  16695.  
  16696.  //  Alternative method:
  16697.  //  while (kbhit()) getch();
  16698.  
  16699.  fflush (stdin) ;         // clear stdin's buffer
  16700.  puts ("Should be waiting again.") ;
  16701.  
  16702.  gets (str) ;
  16703.  puts (str) ;
  16704.  }
  16705.  
  16706.  
  16707.  384. SETUP /L Does Not Create SETARGV.OBJ in C
  16708.  
  16709.  Product Version(s): 5.10   | 5.10
  16710.  Operating System:   MS-DOS | OS/2
  16711.  Flags: ENDUSER |
  16712.  Last Modified: 22-MAY-1989    ArticleIdent: Q44001
  16713.  
  16714.  Invoking C Version 5.10 SETUP with the /L command (to rebuild the
  16715.  libraries) should create xSETARGV.OBJ (where x = S,M,C,L) for each
  16716.  memory model chosen if a "C 4.00 compatible names for SETARGV.OBJ"
  16717.  option is requested during setup. However, when the Setup program is
  16718.  invoked with the /L command, it does not generate SETARGV.OBJ for any
  16719.  memory model. Setup does not even copy that file to the destination
  16720.  drive; only the setup for the whole compiler creates xSETARGV.OBJ for
  16721.  different memory models.
  16722.  
  16723.  C 4.00 has four model-specific object modules, xSETARGV.OBJ (where x =
  16724.  S,M,C,L), which you can link into a program to get wild-card expansion
  16725.  for program arguments. In C 5.10 there is only one object SETARGV.OBJ
  16726.  needed for ALL memory models. However, if you have MAKE files which
  16727.  rely on the C 4.00 convention, you may want to tell the Setup program
  16728.  to make COPIES of this file with the appropriate model-specific name.
  16729.  In fact, the modules of xSETARGV.OBJ are all identical and differ only
  16730.  in their names. Renaming SETARGV.OBJ is all that is required.
  16731.  
  16732.  Therefore, if you are using SETUP just to rebuild the libraries and
  16733.  have chosen C 4.00 compatibility, you must find SETARGV.OBJ on the
  16734.  disk labeled "Floating-Point Libraries" and you must copy/rename that
  16735.  file to suit the memory model(s) you have built.
  16736.  
  16737.  
  16738.  385. DOS Append Interfaces with execvp() in C
  16739.  
  16740.  Product Version(s): 5.10
  16741.  Operating System:   MS-DOS
  16742.  Flags: ENDUSER |
  16743.  Last Modified: 25-MAY-1989    ArticleIdent: Q44033
  16744.  
  16745.  The versions of the exec and spawn (with P_OVERLAY) functions that
  16746.  search the path for the child program to be run, fail with run-time
  16747.  error "R6005 not enough memory on exec" if the child is not in the
  16748.  current directory and the DOS APPEND command points to the child's
  16749.  directory.
  16750.  
  16751.  The DOS Versions 3.30 and later APPEND command is used to specify
  16752.  directories for locating data files.
  16753.  
  16754.  APPEND incorrectly finds .EXE and .COM files when DOS interrupt 21
  16755.  hex, function 3D hex (open file) is called. This can cause the C
  16756.  library function sopen() to mistakenly report that it has succeeded in
  16757.  finding a .COM or .EXE file in the current directory when, in fact,
  16758.  the file is in another directory that is pointed to by APPEND.
  16759.  
  16760.  The path-searching versions of the exec and spawn (with P_OVERLAY)
  16761.  functions use sopen() to first try to open the .COM or .EXE file in
  16762.  the current working directory. If sopen() fails because the file is
  16763.  not there, successive directories specified by the PATH are prepended
  16764.  to the child's filename, and sopen() is called again until it
  16765.  successfully opens the child's file in one of the directories
  16766.  specified by the PATH.
  16767.  
  16768.  If the child is not in the current working directory, but is pointed
  16769.  to by APPEND, sopen() mistakenly reports that it has successfully
  16770.  opened the child in the current directory and the necessary path is
  16771.  not prepended to the child's filename. When the exec/spawn functions
  16772.  call DOS interrupt 21 hex, function 4B hex, subfunction 3 (load and
  16773.  execute overlay program), the child can't be found in the current
  16774.  working directory, and the exec fails. (Unlike DOS function 3D hex to
  16775.  open a file, DOS function 4B hex is not affected by APPEND.) At this
  16776.  point, the only error C exec/spawn functions are designed to report is
  16777.  that there isn't enough memory available for the child process, and
  16778.  the R6005 error is issued.
  16779.  
  16780.  The path searching exec/spawn functions that can be adversely affected
  16781.  by APPEND are execlp, execlpe, execvp, execvpe, spawnlp, spawnlpe,
  16782.  spawnvp, and spawnvpe. The spawn functions using P_WAIT are not
  16783.  affected by APPEND since they do not use sopen().
  16784.  
  16785.  The Microsoft C run-time library functions do not support the use of
  16786.  APPEND. There are no plans to do so in the future.
  16787.  
  16788.  To work around problems caused by APPEND, disabling APPEND with the
  16789.  DOS command "APPEND;" is recommended. Or, within a program, you may
  16790.  use the system() library function for this purpose (except for
  16791.  versions of DOS that support the /E APPEND option to place APPEND in
  16792.  the environment table). If your program needs to accommodate APPEND,
  16793.  you could use the _searchenv() function to obtain the path. Then
  16794.  traverse the path prepending successive drive and directory names to
  16795.  the child's filename for use with sopen() until an sopen() call
  16796.  returns a valid file handle indicating the child program has been
  16797.  found. Once you have the exact path of the .EXE or .COM file, pass
  16798.  the complete path the the appropriate exec?? or spawn?? function.
  16799.  
  16800.  Note: DON'T use one of the functions that has a "p" in its name --
  16801.  these functions search the path for the file, something you've
  16802.  already done if you've followed these directions.
  16803.  
  16804.  
  16805.  386. Using Presentation Graphics/Fonts with C 5.00 and C 5.10
  16806.  
  16807.  Product Version(s): 5.00 5.10
  16808.  Operating System:   MS-DOS
  16809.  Flags: ENDUSER | S_QuickC
  16810.  Last Modified: 25-JUL-1989    ArticleIdent: Q44076
  16811.  
  16812.  It is possible to use the QuickC Version 2.00 presentation graphics
  16813.  and fonts library functions with C 5.00 or C 5.10. However, you must
  16814.  be certain that all of the header files and libraries are from the
  16815.  QuickC 2.00 package. If you attempt to compile a presentation graphics
  16816.  program with C 5.10 and keep getting "unresolved external" messages
  16817.  after carefully linking in GRAPHICS.LIB and PGCHART.LIB, reinstall the
  16818.  default library and GRAPHICS.LIB from the QuickC 2.00 distribution
  16819.  disks. Mixing the C 5.10 and QuickC 2.00 libraries results in this
  16820.  behavior.
  16821.  
  16822.  Please note that the QuickC 2.00 libraries do not support alternate
  16823.  math. The QuickC 2.00 and the C 5.10 libraries cannot be mixed.
  16824.  Therefore, there is no support for the alternate math package under C
  16825.  5.10 when using presentation graphics or font library functions.
  16826.  
  16827.  The unresolved externals that you get when mixing libraries are not
  16828.  functions; they are the names of support routines and new variables
  16829.  that do not exist in the default library or GRAPHICS.LIB from the C
  16830.  5.10 package.
  16831.  
  16832.  
  16833.  387. Allocation of Variables within Blocks in C
  16834.  
  16835.  Product Version(s): 5.00 5.10 | 5.10
  16836.  Operating System:   MS-DOS    | OS/2
  16837.  Flags: ENDUSER | S_QuickC
  16838.  Last Modified: 23-MAY-1989    ArticleIdent: Q44078
  16839.  
  16840.  The "Microsoft C for the MS-DOS Operating System: Language Reference"
  16841.  manual in Section 3.5.2 states the following:
  16842.  
  16843.     An item with a local lifetime (a "local item") has storage and a
  16844.     defined value only within the block where the item is defined or
  16845.     declared. A local item is allocated new storage each time the
  16846.     program enters that block, and it loses its storage (and hence its
  16847.     value) when the program exits the block.
  16848.  
  16849.  This statement is true for function blocks. All nonstatic variables
  16850.  within a function, whether they are within a block or not, are
  16851.  allocated space from the stack upon entry to the function.
  16852.  
  16853.  According to the ANSI standard, the C language should support jumps
  16854.  into blocks. To ensure that variables always are allocated, regardless
  16855.  of the entry point into the block, the space for local variables
  16856.  within a block must be allocated upon entry of the function, not the
  16857.  block. Consider the following code example:
  16858.  
  16859.  int checkup (int var)
  16860.  {
  16861.        .
  16862.        .
  16863.        .
  16864.      if (var)
  16865.         goto test2;
  16866.      else
  16867.      {
  16868.         char buffer[80];
  16869.           strcpy (buffer, "This is a different test");
  16870.         test1:
  16871.           strcpy (buffer, "This is a test");
  16872.             .
  16873.             .
  16874.             .
  16875.      }
  16876.      test2:
  16877.         printf("testing stuff is coming up next");
  16878.         goto test1;
  16879.      return (0);
  16880.  }
  16881.  
  16882.  Although this is not the best way to implement this code sample, this
  16883.  method should be legal, according to the ANSI standard. If the block
  16884.  is entered through the label test1, and the array of characters has
  16885.  not been allocated on the stack previously, the strcpy after the test1
  16886.  label does not work properly. To ensure that "buffer" is allocated
  16887.  space, it is allocated stack space upon entry to the function, and not
  16888.  upon entry to the block.
  16889.  
  16890.  Note: The 80-character buffer is removed from the stack upon exit from
  16891.  the block, and not upon exit from the function.
  16892.  
  16893.  
  16894.  388. File Buffers Are Not Allocated until First Accessed
  16895.  
  16896.  Product Version(s): 5.00 5.10 | 5.10
  16897.  Operating System:   MS-DOS    | OS/2
  16898.  Flags: ENDUSER | s_quickc
  16899.  Last Modified: 22-MAY-1989    ArticleIdent: Q44178
  16900.  
  16901.  Problem:
  16902.  
  16903.  I am using _memavl() to determine the amount of free space on the near
  16904.  heap. When I use fgets(), the amount of near heap space decreases by
  16905.  512 bytes.
  16906.  
  16907.  Response:
  16908.  
  16909.  File buffers are not allocated when the file is first opened. The
  16910.  512-byte buffer is allocated on the near heap when the file is first
  16911.  accessed. The buffer will be used by the file until the file is
  16912.  closed. At that time, the buffer space will be freed to the system.
  16913.  
  16914.  File buffers are allocated in the near heap for small and medium
  16915.  memory models and in the far heap for compact and large memory models.
  16916.  _memavl() returns the amount of free space on the near heap only.
  16917.  
  16918.  The following program, compiled in small or medium memory model,
  16919.  illustrates this behavior:
  16920.  
  16921.  #include <malloc.h>
  16922.  #include <stdio.h>
  16923.  
  16924.  FILE *fp;
  16925.  
  16926.  void main(void)
  16927.  {
  16928.    char bufs[64];
  16929.  
  16930.    printf("Start of program \n");
  16931.    Bytes_free();
  16932.    fp=fopen("file1.txt","r");
  16933.  
  16934.    printf("file1.txt has been opened \n");
  16935.    Bytes_free();
  16936.  
  16937.    fgets(bufs,5,fp);
  16938.    printf(" file has been accessed \n");
  16939.    Bytes_free();
  16940.  
  16941.    fclose(fp);
  16942.    printf(" file has been closed \n");
  16943.    Bytes_free();
  16944.  }
  16945.  
  16946.  Bytes_free()
  16947.  {
  16948.    printf("\nHeap bytes free: %u \n", _memavl()  );
  16949.  }
  16950.  
  16951.  
  16952.  389. BIND: "Structure Error in .EXE File" Caused by Non-FAPI Call
  16953.  
  16954.  Product Version(s): 5.10   | 5.10
  16955.  Operating System:   MS-DOS | OS/2
  16956.  Flags: ENDUSER | SR# G890502-17544
  16957.  Last Modified: 22-MAY-1989    ArticleIdent: Q44205
  16958.  
  16959.  A possible cause of the BIND error message "Structure error in .EXE
  16960.  file" is calling a non-FAPI function from within the program to be
  16961.  bound.
  16962.  
  16963.  The solution is to be sure to call only FAPI functions or to follow
  16964.  the directions in the BIND documentation for programs that make
  16965.  non-FAPI calls.
  16966.  
  16967.  
  16968.  390. Example for freopen Is Incorrect in C, QuickC Manuals
  16969.  
  16970.  Product Version(s): 5.00 5.10 | 5.10
  16971.  Operating System:   MS-DOS    | OS/2
  16972.  Flags: ENDUSER | S_QuickC docerr
  16973.  Last Modified: 19-SEP-1989    ArticleIdent: Q44207
  16974.  
  16975.  There is an error in the sample program given on Page 295 of the
  16976.  "Microsoft C Optimizing Compiler Run-Time Library Reference" for the
  16977.  freopen() function. The first fprintf() function call should be
  16978.  changed to a printf().
  16979.  
  16980.  This error is also present in the QuickC Versions 1.00, 1.01, and 2.00
  16981.  run-time library reference manuals. The sample program has been
  16982.  changed in the QuickC 2.00 on-line help example and is correct there.
  16983.  
  16984.  
  16985.  391. How to Use the ERROUT Utility
  16986.  
  16987.  Product Version(s): 5.10   | 5.10
  16988.  Operating System:   MS-DOS | OS/2
  16989.  Flags: ENDUSER | H_FORTRAN H_MASM docerr
  16990.  Last Modified: 19-SEP-1989    ArticleIdent: Q44388
  16991.  
  16992.  Question:
  16993.  
  16994.  How do I use the ERROUT utility? Examples in the "Microsoft C 5.1
  16995.  Optimizing Compiler/CodeView and Utilities" manual do not seem to
  16996.  work.
  16997.  
  16998.  Response:
  16999.  
  17000.  ERROUT divides its output into two parts: the standard output and the
  17001.  standard error output. If ERROUT is used without the /f switch, error
  17002.  output is sent to standard output. (Normally, error output is sent to
  17003.  the console regardless of where standard output is redirected.) The
  17004.  printed documentation on ERROUT is in error on this point.
  17005.  
  17006.  Therefore, you must use the ERROUT utility with DOS redirection
  17007.  operators ">" or ">>", as in the following example:
  17008.  
  17009.     ERROUT /f err.doc cl test.c > std.doc
  17010.  
  17011.  The file STD.DOC contains the standard output and the file ERR.DOC
  17012.  contains the errors. If there is no error output, the file ERR.DOC
  17013.  will be zero bytes long.
  17014.  
  17015.  To send error output and standard output to the printer, use the
  17016.  following commands:
  17017.  
  17018.     ERROUT cl test.c > PRN
  17019.  
  17020.  To send error output to the printer and standard output to the
  17021.  console, use the following commands:
  17022.  
  17023.     ERROUT /f PRN cl test.c
  17024.  
  17025.  To send error output to the console and standard output to the
  17026.  printer, use the following commands:
  17027.  
  17028.     cl test.c > PRN
  17029.  
  17030.  
  17031.  392. Only Certain C Library Functions Have an Intrinsic Form
  17032.  
  17033.  Product Version(s): 5.10   | 5.10
  17034.  Operating System:   MS-DOS | OS/2
  17035.  Flags: ENDUSER |
  17036.  Last Modified: 30-MAY-1989    ArticleIdent: Q44389
  17037.  
  17038.  The /Oi compiler option generates intrinsic functions instead of
  17039.  function calls only for specified run-time library functions. It does
  17040.  not generate intrinsic functions for all run-time library functions or
  17041.  for application program functions.
  17042.  
  17043.  To approximate intrinsic functions with application code, use the
  17044.  #define directive or the /D compiler option to define a macro.
  17045.  
  17046.  For more information on the /Oi option and the list of functions
  17047.  having intrinsic forms, refer to the "Microsoft C 5.1 Optimizing
  17048.  Compiler User's Guide," Pages 93-94, and the C 5.10 README.DOC, "Part
  17049.  2: Notes for the 'Microsoft C Optimizing Compiler User's Guide.'"
  17050.  
  17051.  
  17052.  393. How to Spawn C 5.10 Compiler Passes without CL.EXE
  17053.  
  17054.  Product Version(s): 5.10
  17055.  Operating System:   MS-DOS
  17056.  Flags: ENDUSER | SR# G890503-17633 c1.exe c2.exe c3.exe
  17057.  Last Modified: 22-NOV-1989    ArticleIdent: Q44413
  17058.  
  17059.  Question:
  17060.  
  17061.  How can I run the individual compiler passes, C1, C2, and C3, instead
  17062.  of CL.EXE? There isn't enough memory available from my editor to spawn
  17063.  to CL.EXE, but I suspect there may be enough if I call the individual
  17064.  compiler passes.
  17065.  
  17066.  Response:
  17067.  
  17068.  There are a number of problems here. First, the CL.EXE program passes
  17069.  many flags and command-line options to the various passes. You must
  17070.  get these all exactly right. The /d, /Bd, or /Bz CL command-line
  17071.  options, or the PEEK.C program below, can help show what is passed
  17072.  to the various passes. The PEEK program is easiest to use. To use it,
  17073.  we "trick" the CL driver into calling our program instead of the
  17074.  various compiler passes. For instance, to find out what is passed on
  17075.  each of the three passes, you would use the following commands:
  17076.  
  17077.     cl /B1 peek.exe /B2 peek.exe /B3 peek.exe [options] [file]
  17078.  
  17079.  When you do this, the CL driver spawns your program PEEK.EXE rather
  17080.  than the various compiler passes. The switches are too complicated to
  17081.  guess at, so either use this program or one of the /B or /d options.
  17082.  Note that no compilation will be done because you called PEEK.EXE
  17083.  rather than the three compiler passes.
  17084.  
  17085.  The second major problem is that because these command strings can
  17086.  easily exceed the DOS 128-character limit on the length of a command
  17087.  line, the CL driver uses the environment string area rather than the
  17088.  command line to pass options to the passes. To duplicate this, you
  17089.  must do one of the following two things:
  17090.  
  17091.  1. Write a batch file that sets the environment properly and calls
  17092.     the various passes. This file fails if any of the strings are
  17093.     longer than the DOS command-line limit of 128 characters. Since
  17094.     this is likely to be the case, you'll probably need to use the
  17095.     second method.
  17096.  
  17097.  2. Write a small C program that spawns (using one of the spawnle,
  17098.     spawnlpe, spawnve, or spawnvpe functions with the P_WAIT option)
  17099.     the three passes, setting up the environment first. This is a
  17100.     simple procedure and provides you with 30K or so in savings. This
  17101.     program is not provided here -- you must write it yourself.
  17102.  
  17103.  PEEK.C Program
  17104.  --------------
  17105.  
  17106.  #include <stdio.h>
  17107.  
  17108.  void main(int argc, char **argv, char **envp)
  17109.  {
  17110.      int i;
  17111.  
  17112.      printf("Command line arguments:\n\n");
  17113.      for (i = 0; i < argc; i++)  {
  17114.          printf("argv[%d]**********\n%s\n\n", i, argv[i]);
  17115.      }
  17116.      printf("**********End of command line arguments\n\n\n");
  17117.  
  17118.      printf("Environment strings:\n\n");
  17119.      for (i = 0; envp[i]; i++)  {
  17120.          printf("envp[%d]**********\n%s\n\n", i, envp[i]);
  17121.      }
  17122.      puts("**********End of environment strings\n");
  17123.  }
  17124.  
  17125.  
  17126.  394. -Zg Won't Handle Untagged Aggregate typedef Parameters
  17127.  
  17128.  Product Version(s): 5.00 5.10 | 5.10
  17129.  Operating System:   MS-DOS    | OS/2
  17130.  Flags: ENDUSER |
  17131.  Last Modified:  1-JUN-1989    ArticleIdent: Q44452
  17132.  
  17133.  The -Zg switch causes the Microsoft C Version 5.10 Optimizing Compiler
  17134.  to generate a list of function prototypes from the input file. This is
  17135.  documented on Page 86 of the "Microsoft C for the MS-DOS Operating
  17136.  System: User's Guide."
  17137.  
  17138.  It is noted on Page 87 of the same manual that structure, enumerated,
  17139.  and union types that are used as formal parameters must be tagged.
  17140.  Using untagged aggregate types as formal parameters results in the
  17141.  following message being generated for each instance of untagged
  17142.  aggregate type parameters:
  17143.  
  17144.     warning C4032 : unnamed struct/union as parameter
  17145.  
  17146.  Typedefs are expanded in the prototype listing. If an aggregate type
  17147.  has no tag then the prototype is commented out and the type of the
  17148.  parameter is labeled, in the case of a structure, as follows:
  17149.  
  17150.     struct UNNAMED
  17151.  
  17152.  There is no way to prevent the compiler from expanding the typedefs
  17153.  and from disliking the untagged aggregate types.
  17154.  
  17155.  The program below, when compiled in the following manner
  17156.  
  17157.     cl -Zg whack.c
  17158.  
  17159.  produces the following output:
  17160.  
  17161.      extern  void main(void );
  17162.      extern  int Woof(struct ure a);
  17163.      /* int Heave(struct UNNAMED a); */
  17164.      whack.c(29) : warning C4032 : unnamed struct/union as parameter
  17165.  
  17166.  /* Demonstration of typedef expansion when compiling with /Zg
  17167.   */
  17168.  typedef struct ure      // This one's tagged
  17169.  {
  17170.      int     x;
  17171.      int     y;
  17172.  } URE;
  17173.  
  17174.  typedef struct          // This one's not tagged
  17175.  {
  17176.      int     x;
  17177.      int     y;
  17178.  } IME;
  17179.  
  17180.  void main()
  17181.  {
  17182.      URE     Ok;         // Tagged type variable
  17183.      IME     NotOk;      // Untagged type variable
  17184.  
  17185.      Woof( Ok );
  17186.      Heave( NotOk );
  17187.  }
  17188.  
  17189.  int Woof( URE a )
  17190.  {
  17191.      return( 0 );
  17192.  }
  17193.  
  17194.  int Heave( IME a )
  17195.  {
  17196.      return( 0 );
  17197.  }
  17198.  
  17199.  
  17200.  395. Using ILINK in the Development Process in C
  17201.  
  17202.  Product Version(s): 5.10   | 5.10
  17203.  Operating System:   MS-DOS | OS/2
  17204.  Flags: ENDUSER | docerr S_QuickC
  17205.  Last Modified: 19-SEP-1989    ArticleIdent: Q44462
  17206.  
  17207.  The incremental linker is available with the Microsoft C Optimizing
  17208.  Compiler Version 5.10 and QuickC Version 2.00. The information below
  17209.  is excerpted from the "Microsoft CodeView and Utilities Software
  17210.  Development Tools for MS OS/2 and MS-DOS Operating Systems Update" for
  17211.  Version C 5.10, Section 9, "The ILINK Utility."
  17212.  
  17213.  Note: The incremental linker supplied with C Version 5.10 CANNOT be
  17214.  used to develop DOS applications other than Windows applications. It
  17215.  can be used for Windows applications and OS/2 applications. This
  17216.  limitation is documented at the beginning of "The ILINK Utility"
  17217.  section in the Version 5.10 utilities update.
  17218.  
  17219.  To develop a software project with ILINK when compiling and linking
  17220.  from the command line, do the following:
  17221.  
  17222.  1. Use the full linker, LINK.EXE, during early development stages
  17223.     until you have a number of different code and data segments.
  17224.  
  17225.  2. Prepare for incremental linking by using the /INC (incremental)
  17226.     option, for example:
  17227.  
  17228.        link /INC file1 file2 ... filen;
  17229.  
  17230.  3. Use the incremental linker, ILINK.EXE, after any small changes
  17231.     are made, for example:
  17232.  
  17233.        ilink /i file1 file2 ... filen
  17234.  
  17235.     To view ILINK options, type ILINK at the DOS prompt and press
  17236.     ENTER.
  17237.  
  17238.  4. Relink with LINK after any major changes are made. Often, a
  17239.     major change causes ILINK to fail and then calls a full LINK.
  17240.     Relinking with LINK alleviates this unnecessary step.
  17241.  
  17242.  5. Repeat Steps 3 and 4 as necessary.
  17243.  
  17244.  To use the same development process with the QuickC Version 2.00
  17245.  environment, you can toggle on and off the incremental compile and
  17246.  incremental link switches. You can find these switches under the
  17247.  Options menu, Make option, in the Compiler Flag selection and Linker
  17248.  Flag selection, respectively.
  17249.  
  17250.  Linking with the /INC option may take longer than without the option
  17251.  because of additional overhead involved in preparing for incremental
  17252.  linking.
  17253.  
  17254.  The /INC linker option is not compatible with the /EXEPACK option.
  17255.  
  17256.  If you compile and link at the command line with QCL using the /Gi
  17257.  (incremental compile) option, then incremental link is automatically
  17258.  invoked. If you do not want an incremental compile you can still
  17259.  request incremental link with the /Li compiler option.
  17260.  
  17261.  
  17262.  396. Difference between Arrays and Pointers in C
  17263.  
  17264.  Product Version(s): 5.10   | 5.10
  17265.  Operating System:   MS-DOS | OS/2
  17266.  Flags: ENDUSER | SR# G890510-18105 S_QuickC
  17267.  Last Modified: 19-SEP-1989    ArticleIdent: Q44463
  17268.  
  17269.  Question:
  17270.  
  17271.  My program is divided into several modules. In one module, I declare
  17272.  an array with the following declaration:
  17273.  
  17274.     signed char buffer[100];
  17275.  
  17276.  In another module, I access the variable with one of the following:
  17277.  
  17278.     extern signed char *buffer;           /* FAILS */
  17279.     extern signed char buffer[];          /* WORKS */
  17280.  
  17281.  Using CodeView reveals that the program is using the wrong address
  17282.  for the array in the first case. The second case works correctly.
  17283.  
  17284.  What is the difference between an array and a pointer.
  17285.  
  17286.  Response:
  17287.  
  17288.  This is a C programming mistake. The following declarations are NOT
  17289.  the same:
  17290.  
  17291.     char *pc;
  17292.     char ac[20];
  17293.  
  17294.  The first declaration sets aside memory for a pointer; the second sets
  17295.  aside memory for 20 characters.
  17296.  
  17297.  A picture of pc and ac in memory might appear as follows:
  17298.  
  17299.      pc  +--------+
  17300.          |   ???  |
  17301.          +--------+
  17302.  
  17303.      ac  +-----+-----+-----+-----+     +-----+
  17304.          |  ?  |  ?  |  ?  |  ?  | ... |  ?  |
  17305.          +-----+-----+-----+-----+     +-----+
  17306.  
  17307.  The same is true for the following:
  17308.  
  17309.     extern char *pc;
  17310.     extern char ac[];
  17311.  
  17312.  Thus, to access the array in ac in another module, the correct
  17313.  declaration is as follows:
  17314.  
  17315.     extern signed char ac[];
  17316.  
  17317.  In your case, the correct declaration is the following:
  17318.  
  17319.     extern char buffer[];
  17320.  
  17321.  The first declaration says that there's a pointer to char called pc
  17322.  (which is two or four bytes) somewhere out there; the second says that
  17323.  there's an actual array of characters called ac.
  17324.  
  17325.  The addressing for pc[3] and ac[3] is done differently. There are some
  17326.  similarities; specifically, the expression "ac" is a constant pointer
  17327.  to char that points to &ac[0]. The similarity ends there, however.
  17328.  
  17329.  To evaluate pc[3], we first load the value of the pointer pc from
  17330.  memory, then we add 3. Finally, we load the character which is stored
  17331.  at this location (pc + 3) into a register. The MASM code might appear
  17332.  as follows (assuming small-memory model):
  17333.  
  17334.     MOV     BX, pc          ; move *CONTENTS* of pc into BX
  17335.                             ; BX contains 1234
  17336.     MOV     AL, [BX + 3]    ; move byte at pc + 3 (1237) into AL
  17337.                             ; ==> AL contains 'd'
  17338.  
  17339.  A picture might appear as follows, provided that pc had been properly
  17340.  set to point to an array at location 1234 and that the array contained
  17341.  "abcd" as its first four characters:
  17342.  
  17343.  address:   1000                  1234  1235  1236  1237
  17344.      pc  +--------+--->>>>>------v-----v-----v-----v-----+
  17345.          |  1234  |          *pc |  a  |  b  |  c  |  d  | ...
  17346.          +--------+              +-----+-----+-----+-----+
  17347.                                   pc[0] pc[1] pc[2] pc[3]
  17348.                                   *pc   *(pc+1) etc.
  17349.  
  17350.  Note: Using pc without properly initializing it (a simple way to
  17351.  initialize it is "pc = malloc(4);" or "pc = ac;") causes you to access
  17352.  random memory you didn't intend to access (and causes the strange
  17353.  behavior).
  17354.  
  17355.  Since ac is a constant, it can be built into the final MOV command,
  17356.  eliminating the need for two MOVs. The MASM code might appear as
  17357.  
  17358.     MOV     AL, [offset ac + 3]     ; mov byte at ac + 3 into AL
  17359.                                     ; offset ac is 1100, so move
  17360.                                     ; byte at 1103 into AL
  17361.                                     ; ==> AL contains 'd'
  17362.  
  17363.  and the picture appears as follows:
  17364.  
  17365.  address: 1100  1101  1102  1103        1119
  17366.      ac  +-----+-----+-----+-----+     +-----+
  17367.          |  a  |  b  |  c  |  d  | ... |  \0 |
  17368.          +-----+-----+-----+-----+     +-----+
  17369.          ac[0] ac[1] ac[2] ac[3]       ac[19]
  17370.          *ac   *(ac+1)  etc.
  17371.  
  17372.  Note: If you first initialize pc to point to ac (by saying "pc =
  17373.  ac;"), then the end effect of the two statements is exactly the same.
  17374.  (This change can be shown in the picture by changing pc so it contains
  17375.  the address of ac, which is 1100.) However, the instructions used to
  17376.  produce these effects are different.
  17377.  
  17378.  Note: If you declared ac to be as follows, the compiler would generate
  17379.  code to do pointer-type addressing rather than array-type addressing:
  17380.  
  17381.     extern char *ac;  /* WRONG! */
  17382.  
  17383.  It would use the first few bytes of the array as an address (rather
  17384.  than characters) and access the memory stored at that location. This
  17385.  is what you're doing and why you're having problems.
  17386.  
  17387.  
  17388.  397. Use /ND Instead of #pragma data_seg
  17389.  
  17390.  Product Version(s): 5.10   | 5.10
  17391.  Operating System:   MS-DOS | OS/2
  17392.  Flags: ENDUSER |
  17393.  Last Modified: 26-MAY-1989    ArticleIdent: Q44477
  17394.  
  17395.  Support for the data_seg pragma may be eliminated from future versions
  17396.  of the Microsoft C Optimizing Compiler. Microsoft strongly recommends
  17397.  that you use the /ND option at compile time instead of embedding the
  17398.  data_seg pragma in your source code.
  17399.  
  17400.  When you use /ND to change the name of the default data segment for a
  17401.  given module, your program can no longer assume that the address
  17402.  contained in the stack segment register (SS) is the same as the
  17403.  address in the data segment (DS). You must also compile with /Au or
  17404.  use the _loadds keyword. A _loadds function loads its own data segment
  17405.  upon entry.
  17406.  
  17407.  All modules whose data segments have the same name have these segments
  17408.  combined into a single segment at link time, including all data that
  17409.  would otherwise be allocated in the _DATA segment, i.e., all
  17410.  subsequent initialized static and global data.
  17411.  
  17412.  See the "Microsoft C 5.1 Optimizing Compiler User's Guide," Section
  17413.  6.7, "Naming Modules and Segments," Pages 157-159, for more detail.
  17414.  
  17415.  The data_seg pragma specifies the name of the data segment that
  17416.  subsequent _loadds functions should use and also causes the named
  17417.  segment to contain all data that would otherwise be allocated in the
  17418.  _DATA segment.
  17419.  
  17420.  Note that the use of pragma data_seg by itself does not cause
  17421.  subsequent functions to load DS. You must also compile with /Au or use
  17422.  the _loadds keyword.
  17423.  
  17424.  
  17425.  398. Ellipse Not Bounded Correctly
  17426.  
  17427.  Product Version(s): 5.00 5.10
  17428.  Operating System:   MS-DOS
  17429.  Flags: ENDUSER | S_QuickC
  17430.  Last Modified: 26-MAY-1989    ArticleIdent: Q44523
  17431.  
  17432.  The _ellipse function does not behave as defined. The Microsoft QuickC
  17433.  and Optimizing C 5.x run-time library reference manuals state that
  17434.  "the bounding rectangle [is] defined by the logical points (x1,y1) and
  17435.  (x2,y2)." However, the bound specified by y2 may be two pixels distant
  17436.  from the lowest point reached by the ellipse.
  17437.  
  17438.  This behavior can be demonstrated in any video mode, but not all
  17439.  possible bounding points will produce this behavior.
  17440.  
  17441.  This "off by two" behavior is especially troublesome when floodfilling
  17442.  a region bounded by the ellipse and a line on y2. The floodfill will
  17443.  bleed out of what should be an enclosed region. The following program
  17444.  demonstrates this situation:
  17445.  
  17446.  #include <graph.h>
  17447.  
  17448.  void main (void)
  17449.  {
  17450.    int x1=0, y1=0, x2=639, y2=349;
  17451.  
  17452.    _setvideomode (_ERESCOLOR);
  17453.  
  17454.    /* Draw the boundary. */
  17455.    _setcolor  (15);
  17456.    _rectangle (_GBORDER, x1, y1, x2, y2);
  17457.    _ellipse   (_GBORDER, x1, y1, x2, y2);
  17458.  
  17459.    /* Define _floodfill attributes. */
  17460.    _moveto    (x1+1, y2-1);
  17461.    _setcolor  (12);
  17462.  
  17463.    /* This should not 'bleed' to the right region. */
  17464.    _floodfill (x1+1, y2-1, 15);
  17465.  }
  17466.  
  17467.  Microsoft is researching this problem and will post new information as
  17468.  it becomes available.
  17469.  
  17470.  
  17471.  399. UNLINK Does Not Work If the File Is Not Closed
  17472.  
  17473.  Product Version(s): 4.00 5.00 | 5.10
  17474.  Operating System:   MS-DOS    | OS/2
  17475.  Flags: ENDUSER | S_QuickC
  17476.  Last Modified:  1-JUN-1989    ArticleIdent: Q44608
  17477.  
  17478.  Question:
  17479.  
  17480.  I am using the function UNLINK to delete a file. UNLINK seems to
  17481.  delete the file, but I do not get the disk space back. Why?
  17482.  
  17483.  Response:
  17484.  
  17485.  The C run-time function UNLINK does not work properly if the file you
  17486.  are trying to delete is not closed. If the file is not closed, the
  17487.  File Allocation Table is not be updated properly and CHKDSK reports
  17488.  lost clusters. These lost clusters are the unclosed files which tried
  17489.  to delete.
  17490.  
  17491.  You can recover the lost disk space by running CHKDSK /F. This
  17492.  information also applies to the C run-time function REMOVE.
  17493.  
  17494.  
  17495.  400. printf() and 512-Byte I/O Buffer
  17496.  
  17497.  Product Version(s): 5.10   | 5.10
  17498.  Operating System:   MS-DOS | OS/2
  17499.  Flags: ENDUSER | S_QuickC
  17500.  Last Modified: 15-AUG-1989    ArticleIdent: Q44725
  17501.  
  17502.  Question:
  17503.  
  17504.  Why does the function printf() take up 512 bytes from the near heap
  17505.  (in small and medium memory model) when compiled with QuickC 2.00 but
  17506.  does not seem to take up any memory using C 5.10 or QuickC 1.01?
  17507.  
  17508.  Response:
  17509.  
  17510.  In QuickC 2.00, the standard I/O buffer gets allocated only when
  17511.  needed. This gives the program an extra 512 bytes of near heap space
  17512.  in small and medium memory model or an extra 512 bytes of far heap
  17513.  space in compact and large model. Therefore, when the printf()
  17514.  function is used for the first time, a 512-byte buffer is reserved
  17515.  for I/O, and the subsequent calls to printf() use that buffer.
  17516.  
  17517.  In C 5.10 and QuickC 1.01, a 512-byte buffer is always reserved at
  17518.  start-up. It doesn't matter if the program uses standard I/O or not.
  17519.  The buffer is also always allocated in the near heap, no matter what
  17520.  memory model is used.
  17521.  
  17522.  The following program prints the amount of space left in the near
  17523.  heap. When complied under C 5.10 or QuickC 1.01, the number is the
  17524.  same before and after the execution of printf().
  17525.  
  17526.  The program also uses _fheapwalk to show that C 5.10 and QuickC 1.01
  17527.  always allocate the buffer in the near heap in any memory model, and
  17528.  QuickC 2.00 allocates it in the near or far heap according to the
  17529.  memory model.
  17530.  
  17531.  When compiled under QuickC 2.00, the number printed after the printf()
  17532.  function is executed is 512 bytes fewer than the number printed before
  17533.  the execution of printf().
  17534.  
  17535.  #include <stdio.h>
  17536.  #include <math.h>
  17537.  #include <dos.h>
  17538.  #include <malloc.h>
  17539.  
  17540.  void heapdump (void);
  17541.  void main (void)
  17542.  {
  17543.    unsigned n1, n2;
  17544.  
  17545.    n1 = _memavl();
  17546.    heapdump();
  17547.    printf("first printf has been executed\n");
  17548.    n2 = _memavl();
  17549.    printf("space left in the near heap before printf %u\n",n1);
  17550.    printf("space left in the near heap after printf %u\n",n2);
  17551.    heapdump();
  17552.  }
  17553.  
  17554.  void heapdump (void)
  17555.  {
  17556.    struct _heapinfo hinfo;
  17557.    int heapstatus;
  17558.  
  17559.    hinfo._pentry = NULL;
  17560.    while ((heapstatus = _fheapwalk(&hinfo)) == _HEAPOK)
  17561.    {
  17562.       printf("%6s block at %p of size %d in the far heap\n",
  17563.             (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
  17564.             hinfo._pentry, hinfo._size);
  17565.    }
  17566.    switch (heapstatus)
  17567.    {
  17568.      case _HEAPEMPTY:
  17569.          printf("OK - empty far heap\n");
  17570.          break;
  17571.      case _HEAPEND:
  17572.          printf("OK - end of far heap\n");
  17573.          break;
  17574.      case _HEAPBADPTR:
  17575.          printf("ERROR - bad pointer\n");
  17576.          break;
  17577.      case _HEAPBADBEGIN:
  17578.          printf("ERROR - bad start\n");
  17579.          break;
  17580.      case _HEAPBADNODE:
  17581.          printf("ERROR - bad node\n");
  17582.          break;
  17583.    }
  17584.  }
  17585.  
  17586.  
  17587.  
  17588.  401. Using Third-Party Libraries Produced for C Version 4.00
  17589.  
  17590.  Product Version(s): 4.00 5.00 5.10 | 5.10
  17591.  Operating System:   MS-DOS         | OS/2
  17592.  Flags: ENDUSER | S_QuickC
  17593.  Last Modified: 31-MAY-1989    ArticleIdent: Q44793
  17594.  
  17595.  Third-party libraries made for C Version 4.00 can be used with C
  17596.  Versions 5.00 and C 5.10. An attempt was made to make third-party
  17597.  libraries as compatible as possible. However, a few functions were
  17598.  changed to conform to the ANSI C draft and may cause problems.
  17599.  Functions such as rename() and memcpy() had their arguments reversed
  17600.  from the C 4.00 to C 5.00 libraries; thus, calls to these functions
  17601.  from C 4.00 libraries do not work properly. This also applies when
  17602.  using third-party libraries with QuickC 1.x and QuickC 2.00.
  17603.  
  17604.  To use libraries made for C 4.00 under C 5.00 or above, you must link
  17605.  with /NOD and specify the C 5.00 combined library to use, as follows
  17606.  (the /NOD tells the linker not to use the default libraries for C 4.00):
  17607.  
  17608.     LINK /NOD file.c ,,, oldlib slibce.lib
  17609.  
  17610.  In QuickC, this can be done as follows by setting the environment
  17611.  variable LINK to /NOD and specifying the QuickC combined library to
  17612.  use in a program list:
  17613.  
  17614.     set LINK=/NOD
  17615.  
  17616.  If there are still linker errors, you must request library updates
  17617.  from the third-party vendor.
  17618.  
  17619.  
  17620.  402. printf Appears to Print Incorrect Results for Floats
  17621.  
  17622.  Product Version(s): 5.10 | 5.10
  17623.  Operating System:   DOS  | OS/2
  17624.  Flags: ENDUSER |
  17625.  Last Modified:  1-JUN-1989    ArticleIdent: Q44816
  17626.  
  17627.  Question:
  17628.  
  17629.  The printf() below does not print out the correct values for the float
  17630.  if I print the float with a hexadecimal specifier before the float
  17631.  specifier. Is this a problem with the code or printf()?
  17632.  
  17633.  Response:
  17634.  
  17635.  The problem here is that we are using a 2-byte format specifier for an
  17636.  8-byte value. To correct this problem, replace "%x" and "%lx" with
  17637.  "%lx %lx".
  17638.  
  17639.  Code example
  17640.  ------------
  17641.  
  17642.  #include <stdio.h>
  17643.  main()
  17644.  {
  17645.          float flt  = 1.701411e+038;
  17646.          double dbl = 1.701411e+038;
  17647.  
  17648.   printf("\nFLOAT         %x   %e", flt,flt);
  17649.   printf("\nDOUBLE        %lx  %le",dbl,dbl);
  17650.  }
  17651.  
  17652.  The above code produces incorrect output. However, the source code is
  17653.  incorrect. When printing, the above code is using a 2-byte hex format
  17654.  specifier %x or a 4-byte hex format specifier %lx with an 8-byte
  17655.  double argument (the float is also passed as a double). This produces
  17656.  the incorrect results. To solve this problem, use two %lx format
  17657.  specifiers to remove 8-bytes off the stack before printing the second
  17658.  double. An example is as follows:
  17659.  
  17660.     printf("\nFloat  %lx %lx %e",flt,flt);
  17661.     printf("\nDouble %lx %lx %le",dbl,dbl);
  17662.  
  17663.  This works correctly for Microsoft C under MS-DOS or OS/2; however,
  17664.  this code may not be portable under other systems that support types
  17665.  of different sizes.
  17666.  
  17667.  Eight bytes are passed, independent of the fact that one argument is a
  17668.  float and the other a double, because the float is being promoted to a
  17669.  double. This is because all floats are passed as doubles unless they
  17670.  are specified as floats in the prototype. Because printf() has
  17671.  variable number of parameters, the arguments are not prototyped and
  17672.  therefore all floats are promoted up to doubles.
  17673.  
  17674.  
  17675.  403. Software/Hardware Required for Writing Windows Applications
  17676.  
  17677.  Product Version(s): 5.10
  17678.  Operating System:   MS-DOS
  17679.  Flags: ENDUSER | S_QuickC P_WinSDK
  17680.  Last Modified: 26-MAY-1989    ArticleIdent: Q44834
  17681.  
  17682.  To write programs for Windows, you need the following software
  17683.  packages:
  17684.  
  17685.  1. Microsoft Windows/286 or Windows/386 Version 2.00 or later.
  17686.  
  17687.  2. Microsoft Windows Software Development Kit (SDK) Version 2.00 or
  17688.     later.
  17689.  
  17690.     Note: The version number for the Windows package must match
  17691.     the version number for the SDK, e.g. Windows 2.0x with SDK 2.00
  17692.     or Windows 2.1x with SDK 2.10.
  17693.  
  17694.  3. Microsoft C Compiler Version 4.00 or later, Microsoft QuickC
  17695.     Version 2.00, or another compiler suitable for compiling Windows
  17696.     programs.
  17697.  
  17698.  4. Microsoft Macro Assembler 4.00 or later (for writing DLLs).
  17699.  
  17700.  To run Windows and the Windows Software Development Kit, you need the
  17701.  following hardware:
  17702.  
  17703.  1. An IBM personal computer (or compatible) with a fixed disk and
  17704.     640K of memory running MS-DOS Version 3.00 or later. (A machine
  17705.     based on an 80286 or 80386 microprocessor with a fast fixed disk is
  17706.     best.)
  17707.  
  17708.  2. A graphics display and video board, preferably an Enhanced Graphics
  17709.     Adapter (EGA) or Video Graphics Array (VGA). A Color Graphics
  17710.     Adapter (CGA), Hercules Graphics Card or compatible, or an IBM 8514
  17711.     can also be used.
  17712.  
  17713.  3. A mouse (optional).
  17714.  
  17715.  To debug with CodeView (CVW) you need the following:
  17716.  
  17717.  1. 1.5 MB of LIM 4.00 expanded memory (2 MB or more is recommended).
  17718.  
  17719.  2. Either dual monitors (the second of which is monochrome, the first
  17720.     a CGA, EGA, or VGA) or a dumb terminal connected to COM1.
  17721.  
  17722.     Note: In a dual-monitor setup, when the primary monitor is a CGA,
  17723.     the Windows on the CGA is in monochrome due to resolution and the
  17724.     monochrome monitor is in text.
  17725.  
  17726.  Windows/286 can run under DOS or in the DOS compatibility box under
  17727.  OS/2 on an 80286 or 80386. Windows/386 requires an 80386 where it can
  17728.  run under DOS but not in the DOS compatibility box. Typing "WIN86"
  17729.  (without the quotation marks) at the DOS prompt (or DOS box) initiates
  17730.  a 80286 (not a 80386) session.
  17731.  
  17732.  
  17733.  404. kbhit() Does Not Take Character Out of Buffer
  17734.  
  17735.  Product Version(s): 4.00 5.00 5.10 | 5.10
  17736.  Operating System:   MS-DOS         | OS/2
  17737.  Flags: ENDUSER | S_QuickC
  17738.  Last Modified: 26-MAY-1989    ArticleIdent: Q44895
  17739.  
  17740.  If you are repeatedly testing the value of "!kbhit()", you must fetch
  17741.  the character out of the keyboard buffer yourself after entering a
  17742.  keystroke. If you do not, kbhit() returns TRUE and the test repeatedly
  17743.  fails.
  17744.  
  17745.  The following code demonstrates the situation:
  17746.  
  17747.  #include <conio.h>
  17748.  
  17749.  void main (void)
  17750.  {
  17751.   while (!kbhit ());    /* waits for keystroke */
  17752.   while ( kbhit ())
  17753.      getch ();          /* empties buffer */
  17754.  
  17755.   while (!kbhit ());    /* waits for keystroke */
  17756.   while (!kbhit ());    /* does not wait for keystroke */
  17757.  }
  17758.  
  17759.  
  17760.  405. system() Returns an Exit Code Under OS/2
  17761.  
  17762.  Product Version(s): 5.10   | 5.10
  17763.  Operating System:   MS-DOS | OS/2
  17764.  Flags: ENDUSER |
  17765.  Last Modified: 31-MAY-1989    ArticleIdent: Q44897
  17766.  
  17767.  The system() function under OS/2 returns the exit code of the process
  17768.  executed, unlike MS-DOS. Under MS-DOS the system() function always
  17769.  returns 0 to indicate successful completion.
  17770.  
  17771.  Under both operating systems, if the system() function fails then a
  17772.  value of -1 is returned.
  17773.  
  17774.  
  17775.  406. How Does _osmode Get Set?
  17776.  
  17777.  Product Version(s): 5.10   | 5.10
  17778.  Operating System:   MS-DOS | OS/2
  17779.  Flags: ENDUSER | SR# G890523-18896
  17780.  Last Modified: 21-AUG-1989    ArticleIdent: Q44927
  17781.  
  17782.  The Microsoft C Run-time Library variable _osmode is set to one (1)
  17783.  when running under OS/2 and to zero (0) when running under DOS. A C
  17784.  program can look at this variable and easily determine whether it's
  17785.  running under DOS or OS/2, without calling DosGetMachineMode.
  17786.  
  17787.  To declare the variable, use the following line:
  17788.  
  17789.     #include <stdlib.h>
  17790.  
  17791.  An examination of the start-up code (included with the compiler) shows
  17792.  how the value of this variable is determined. The DOS start-up code
  17793.  just initializes the variable to zero. The OS/2 code initializes it by
  17794.  making a call to the OS/2 API DosGetMachineMode, which sets it to zero
  17795.  for DOS or one for OS/2. Thus, you don't need to make the call.
  17796.  
  17797.  If you compile for DOS (/Lr or /Lc), the DOS start-up code is included
  17798.  because the linker links your program with the appropriate DOS library
  17799.  (xLIBCyR, where x is the memory model and y is the math option). By
  17800.  the same token, when you compile with /Lp, the linker links the proper
  17801.  library for OS/2 (xLIBCyP). If you don't specify one of these options,
  17802.  your code is linked with xLIBCy.
  17803.  
  17804.  
  17805.  407. setbuf() Does Not Control Buffering of DOS or Keyboard Buffer
  17806.  
  17807.  Product Version(s): 5.10
  17808.  Operating System:   MS-DOS
  17809.  Flags: ENDUSER | S_QuickC
  17810.  Last Modified: 25-JUL-1989    ArticleIdent: Q45563
  17811.  
  17812.  Question:
  17813.  
  17814.  Why does getchar() still wait for a carriage return even though I used
  17815.  setbuf() to unbuffer stdin?
  17816.  
  17817.  Response:
  17818.  
  17819.  The function setbuf() affects a stream file buffer like stdin, but has
  17820.  no effect on the keyboard or DOS device buffers. The stream I/O
  17821.  function getchar() can only read a character from the keyboard buffer
  17822.  when the keyboard buffer is flushed by either being filled, by a
  17823.  carriage return, or by an interrupt 0x21, function 0xC call.
  17824.  
  17825.  To read typical characters directly from the keyboard, you can use
  17826.  the console I/O function getch(). To read control codes such as
  17827.  ALT+Q (echo subsequent output to printer) or ALT+R (pause output), you
  17828.  can use the _bios_keybrd() function. Query on the following:
  17829.  
  17830.     _bios_keybrd()
  17831.  
  17832.  The following example demonstrates the difference between using
  17833.  getchar() and getch():
  17834.  
  17835.  #include <stdio.h>
  17836.  #include <conio.h>
  17837.  
  17838.  void main (void)
  17839.  {
  17840.     setbuf (stdin, NULL);        /* cause stdin to be unbuffered */
  17841.     if (getchar () != EOF )
  17842.        printf ("getchar() still waits for return key\n");
  17843.     if (getch () != EOF )
  17844.        printf ("getch() does not wait for return key\n");
  17845.  }
  17846.  
  17847.  
  17848.  408. Installing C 5.10 to Compile Both DOS and OS/2 Programs
  17849.  
  17850.  Product Version(s): 5.10   | 5.10
  17851.  Operating System:   MS-DOS | OS/2
  17852.  Flags: ENDUSER | SR# G890523-18896
  17853.  Last Modified: 18-SEP-1989    ArticleIdent: Q45145
  17854.  
  17855.  If you'd like to install your C compiler so that you can create both
  17856.  DOS and OS/2 applications, you have three options. The option you
  17857.  select affects the compiler options you must set when you compile for
  17858.  the two operating systems.
  17859.  
  17860.  The three options are as follows:
  17861.  
  17862.  1. Rename none of the libraries.
  17863.  
  17864.  2. Rename the protected-mode libraries to the default names.
  17865.  
  17866.  3. Rename the real-mode libraries to the default names. This
  17867.     renaming can also be done while setting up the product.
  17868.  
  17869.  To install for both OS/2 and DOS, select both operating systems when
  17870.  using SETUP to install the product. If you've already installed the
  17871.  product for only one operating system, the easiest method is to
  17872.  reinstall again from the beginning.
  17873.  
  17874.  Once the dual installation is done, you have the following two sets of
  17875.  libraries (unless you tell SETUP to rename libraries for you when it
  17876.  asks):
  17877.  
  17878.  1. Those whose names are of the form xLIBCyR.LIB (where x is S, M, C,
  17879.     or L for the memory model and y is E, 7, or A for the math option --
  17880.     see the Version 5.10 "Microsoft C Optimizing Compiler for the MS-DOS
  17881.     Operating System User's Guide" for more information) for "R"eal mode.
  17882.  
  17883.  2. Those whose names are of the form xLIBCyP.LIB for "P"rotected mode.
  17884.  
  17885.  If you install medium model emulator math only, and don't tell SETUP
  17886.  to rename libraries, the libraries will be named "MLIBCEP.LIB" and
  17887.  "MLIBCER.LIB". There will be no library named with the default name,
  17888.  which is "MLIBCE.LIB".
  17889.  
  17890.  You can leave the libraries named in this way; however, if you do, you
  17891.  must always compile with one of the /Lr (link real mode), /Lc (link
  17892.  compatibility mode -- a synonym for real mode), or /Lp (link protected
  17893.  mode) compiler options.
  17894.  
  17895.  None of the /Lp, /Lc, or /Lp options affects the compilation process;
  17896.  they only affect what libraries the linker is asked to link in.
  17897.  Whether the final executable program is a real-mode executable or a
  17898.  protected-mode executable is determined solely by the library with
  17899.  which you link.
  17900.  
  17901.  The /Lp option tells the linker to ignore the default library and to
  17902.  use xLIBCyP.LIB instead (x and y depend on the memory model and math
  17903.  option selected by the /Ax and /FP switches). The /Lr and /Lc options
  17904.  tell the linker to use xLIBCyR.LIB rather than the default. xLIBCy is
  17905.  the library generated if none of these options is used. This is shown
  17906.  in the following table:
  17907.  
  17908.     Compiler Flags                          Library Used
  17909.     --------------                          ------------
  17910.  
  17911.        -AS                                     SLIBCE
  17912.        -AL -FPi87                              LLIBC7
  17913.        -AM -FPa -Lp                            MLIBCAP
  17914.        -AH -FPc -Lr                            LLIBCER
  17915.  
  17916.  If you do most of your programming for one operating system or the
  17917.  other, you can rename the appropriate libraries (xLIBCyR or xLIBCyP)
  17918.  to xLIBCy and avoid having to use /Lp or /Lr. You still must use /Lp
  17919.  or /Lr when compiling for the other mode. For instance, if you rename
  17920.  the xLIBCyP libraries to xLIBCy, then when you compile without a /Lc
  17921.  or /Lr option, your executable will be a protected-mode executable.
  17922.  To generate a DOS executable, you must use /Lr or /Lc. Instead, if you
  17923.  rename the xLIBCyR libraries to xLIBCy, the default mode will be DOS
  17924.  -- you must use /Lp to produce an OS/2 program.
  17925.  
  17926.  
  17927.  409. Initialization and Discarding of DLLs Built with C Run Time
  17928.  
  17929.  Product Version(s): 5.10
  17930.  Operating System:   OS/2
  17931.  Flags: ENDUSER | softlib CRTDLL.ARC S12104.EXE
  17932.  Last Modified:  5-OCT-1989    ArticleIdent: Q45180
  17933.  
  17934.  Question:
  17935.  
  17936.  Is there a C run-time DLL de-install function provided with
  17937.  LLIBCDLL.LIB that, among other things, removes the DosExitList
  17938.  functions? Using DosFreeModule doesn't work properly.
  17939.  
  17940.  Response:
  17941.  
  17942.  You must do some DLL initialization and cleanup to prevent our default
  17943.  DLL initialization and exit code from including the exit list set up
  17944.  by LLIBCDLL.LIB, and we have files and suggested procedures for this
  17945.  purpose.
  17946.  
  17947.  The OnLine Software/Data Library file CRTDLL contains the files
  17948.  DLLINIT.OBJ and DLLTERM.OBJ, which contain initialization and
  17949.  termination functions for LLIBCDLL. Link these functions in with your
  17950.  own DLL's initialization and termination functions. (CRTDLL also
  17951.  contains CRTDLL_I.OBJ, but this is to replace CRTDLL.OBJ for use with
  17952.  the multiple thread CRTLIB.DLL.)
  17953.  
  17954.  CRTDLL can be found in the Software/Data Library by searching on the
  17955.  keyword CRTDLL, the Q number of this article, or S12104. CRTDLL was
  17956.  archived using the PKware file-compression utility.
  17957.  
  17958.  The prototypes for the functions in DLLINIT.OBJ and DLLTERM.OBJ are,
  17959.  respectively, the following:
  17960.  
  17961.     void far pascal C_INIT(void);
  17962.     void far pascal C_TERM(void);
  17963.  
  17964.  To specify the entry point into your own DLL initialization routine,
  17965.  you must have a MASM file specifying the name of your DLL
  17966.  initialization function with the MASM "END" InitRoutineName statement,
  17967.  as in the following:
  17968.  
  17969.  ; MASM routine
  17970.  ...
  17971.  END InitRoutineName
  17972.  
  17973.  The InitRoutineName can specify a MASM or C routine. For C, the DLL
  17974.  initialization routine would appear similar to the following:
  17975.  
  17976.  void far pascal C_INIT(void);
  17977.  
  17978.  int _export _loadds InitRoutineName() {
  17979.          C_INIT();
  17980.  
  17981.          // ... your own initialization code
  17982.  
  17983.          return(1);  //Indicates to OS/2 that the DLL init succeeded.
  17984.                   //If return(0), OS/2 won't load .EXE's using the DLL
  17985.          }
  17986.  
  17987.  Your own initialization code must not use C run-time library function
  17988.  calls before C_INIT() is called.
  17989.  
  17990.  Link the MASM entry code .OBJ, the module containing the above
  17991.  InitRoutineName() and other DLL functions, and DLLINIT.OBJ together
  17992.  with LLIBCDLL and DOSCALLS.LIB (for OS/2 1.00, or OS2.LIB for OS/2
  17993.  1.10).
  17994.  
  17995.  The DLL's .DEF file must contain the following statements:
  17996.  
  17997.     LIBRARY dllname INITINSTANCE
  17998.     DATA MULTIPLE
  17999.  
  18000.  To eliminate your DLL, write an initialization function in your DLL
  18001.  (or add to the one above) that registers one or more exit routines
  18002.  with DosExitList. The exit routines should free all resources acquired
  18003.  by the DLL that are no longer needed. The C_TERM() function must be
  18004.  called to clean up for LLIBCDLL.
  18005.  
  18006.  Link in DLLTERM.OBJ with this module. DLLTERM.OBJ will suppress our
  18007.  standard use of DosExitList for cleaning up after LLIBCDLL to allow you
  18008.  to create your own exit routine list. (For cleaning up after DLL's use
  18009.  of the multithread CRTLIB.DLL, you must create your own exit routines
  18010.  with C's atexit() or DosExitList.)
  18011.  
  18012.  All the DLL function entries in the exit list must be removed before
  18013.  the .EXE can detach itself from the DLL. To actually discard the DLL,
  18014.  your .EXE must call a final termination routine in the DLL. The final
  18015.  DLL termination routine must remove the other functions in the exit
  18016.  list and then call "DosExitList(EXLST_EXIT, 0L);" to remove itself
  18017.  from the exit list. Then, the DosFreeModule of the DLL should succeed.
  18018.  
  18019.  
  18020.  410. Documented Search Order for Include Files
  18021.  
  18022.  Product Version(s): 5.00 5.10 | 5.10
  18023.  Operating System:   MS-DOS    | OS/2
  18024.  Flags: ENDUSER | docerr
  18025.  Last Modified: 18-SEP-1989    ArticleIdent: Q45187
  18026.  
  18027.  I am having trouble determining the precise search order for include
  18028.  files. The Version 5.10 "Microsoft C for the MS-DOS Operating System:
  18029.  User's Guide" states the following on Page 34:
  18030.  
  18031.     The compiler always searches the current working directory first
  18032.     before searching the locations given in the environment variable.
  18033.  
  18034.  (Except when using < >).
  18035.  
  18036.  The Version 5.10 "Microsoft C for the MS-DOS Operating System:
  18037.  Language Reference" on Page 203 discusses searching in terms of the
  18038.  "parent" file's directory, then also mentions the current working
  18039.  directory in a subsequent paragraph.
  18040.  
  18041.  From my experimenting, it seems that all references to the current
  18042.  working directory are incorrect. The compiler actually searches based
  18043.  on the parent's directory. The MS-DOS current directory is never
  18044.  searched unless it is included on the command line or in the INCLUDE
  18045.  variable.
  18046.  
  18047.  The above assumptions are correct. All references to the "current
  18048.  working directory" should be referring to the "parent" directory. This
  18049.  is a documentation error. If include files are nested, then this error
  18050.  becomes important. With nested include files, the current working
  18051.  directory can be very different from the parent directory. The parent
  18052.  directory is always the one that is searched.
  18053.  
  18054.  
  18055.  411. Run-Time Library FP Signal Handler Assumes SS=DS
  18056.  
  18057.  Product Version(s): 5.10
  18058.  Operating System:   MS-DOS
  18059.  Flags: ENDUSER | softlib CFPLIBS.ARC S12318.EXE
  18060.  Last Modified: 25-JUL-1989    ArticleIdent: Q45195
  18061.  
  18062.  Note that the Microsoft Run-Time Library Exception handler will call
  18063.  another routine that calls the task's SIGFPE signal handler, if one
  18064.  exists.
  18065.  
  18066.  However, this intervening routine assumes that the stack segment is
  18067.  that of the program that caused the 8087 exception. It is known that
  18068.  certain 8087 instructions can take a (relatively) long time to
  18069.  execute. It is also known that other interrupt routines, such as the
  18070.  timer or the disk interrupt or one belonging to a TSR, may in fact be
  18071.  running when the 8087 interrupt occurs.
  18072.  
  18073.  As the NMI, it will nest, and the run-time library routine's
  18074.  assumption about the stack segment may not be valid.
  18075.  
  18076.  This problem is very rare; however, it is a valid concern. Instead of
  18077.  sacrificing speed, the decision was made to take the small chance that
  18078.  SS=DS. Checking for SS=DS would slow the floating-point libraries
  18079.  considerably.
  18080.  
  18081.  There is a file in the OnLine Software/Data Library that contains two
  18082.  floating-point libraries. These libraries should protect you from the
  18083.  unlikely event of SS!=DS. These libraries are approximately 10%
  18084.  slower than the retail floating-point libraries.
  18085.  
  18086.  This file can be found in the Software/Data Library by searching on
  18087.  the keyword CFPLIBS, the Q number of this article, or S12318. CFPLIBS
  18088.  was archived using the PKware file-compression utility.
  18089.  
  18090.  These libraries eliminate the possibility of SS!=DS within a
  18091.  floating-point signal handler. However, these libraries are about 10%
  18092.  slower than the original floating-point libraries. To include these
  18093.  files in your combined libraries, first make backup copies of the
  18094.  original floating-point libraries, rename these new libraries to
  18095.  EM.LIB and 87.LIB, and then run SETUP with the /L option to rebuild
  18096.  libraries. This will rebuild the combined libraries with these new
  18097.  floating-point components.
  18098.  
  18099.  The libraries provided with this archived file are fully tested.
  18100.  However, they are not regularly released with Microsoft C 5.10.
  18101.  Consequently, they will not be maintained, and any problem reported
  18102.  with them will not result in a patch or any other immediate fix.
  18103.  Please report all problems experienced with these libraries.
  18104.  
  18105.  The archived file contains the following files:
  18106.  
  18107.     README.DOC
  18108.     PIEM.LIB
  18109.     PI87.LIB
  18110.  
  18111.  
  18112.  412. _ERESNOCOLOR Is a Monochrome/Graphics Mode
  18113.  
  18114.  Product Version(s): 5.00 5.10
  18115.  Operating System:   MS-DOS
  18116.  Flags: ENDUSER | docerr
  18117.  Last Modified: 22-NOV-1989    ArticleIdent: Q45219
  18118.  
  18119.  On Page 359 of the "Microsoft C for the MS-DOS Operating System:
  18120.  Run-Time Library Reference" for C Versions 5.00 and 5.10 and for
  18121.  QuickC, the video mode specified by _ERESNOCOLOR is incorrectly
  18122.  listed as being a monochrome/text mode. This is really a
  18123.  monochrome/graphics mode. The incorrect line reads as follows:
  18124.  
  18125.     _ERESNOCOLOR   M/T   640x350   1   EGA
  18126.  
  18127.  This line should read as follows:
  18128.  
  18129.     _ERESNOCOLOR   M/G   640x350   2   EGA
  18130.  
  18131.  
  18132.  413. Tzset Sample Program Redefinition Errors in Large Model
  18133.  
  18134.  Product Version(s): 5.10   | 5.10
  18135.  Operating System:   MS-DOS | OS/2
  18136.  Flags: ENDUSER | S_QuickC docerr
  18137.  Last Modified: 25-JUL-1989    ArticleIdent: Q45228
  18138.  
  18139.  The TZSET sample program given on Page 619 of the "Microsoft C 5.1
  18140.  Run-time Library Reference" may yield the following errors:
  18141.  
  18142.     error C2086: 'daylight' : redefinition
  18143.     error C2086: 'timezone' : redefinition
  18144.     error C2086: 'tzname'   : redefinition
  18145.  
  18146.  These errors occur only when compiling for the large or compact-memory
  18147.  models.
  18148.  
  18149.  The errors occur because under the large and compact-memory models,
  18150.  the variable references default to far addresses, which contradicts
  18151.  the external near declarations contained within the include file
  18152.  TIME.H.
  18153.  
  18154.  You may correct this problem by declaring the three variables in
  18155.  your source as follows:
  18156.  
  18157.     int    near daylight;
  18158.     long   near timezone;
  18159.     char * near tzname[];
  18160.  
  18161.  The include file, TIME.H, declares the variables as follows:
  18162.  
  18163.     extern int     near    cdecl daylight;
  18164.     extern long    near    cdecl timezone;
  18165.     extern char *  near    cdecl tzname[2];
  18166.  
  18167.  
  18168.  414. Unsigned Characters and Arithmetic Operators
  18169.  
  18170.  Product Version(s): 5.10   | 5.10
  18171.  Operating System:   MS-DOS | OS/2
  18172.  Flags: ENDUSER | S_QuickC
  18173.  Last Modified: 13-SEP-1989    ArticleIdent: Q45237
  18174.  
  18175.  Question:
  18176.  
  18177.  In the sample program below, I compare two unsigned character
  18178.  variables.  The conditional always evaluates to true, even when x and
  18179.  y are complements. When I examine the assembly code produced, it
  18180.  appears as though the compiler is generating code to compare two
  18181.  unsigned integers, not unsigned characters. Is this a bug?
  18182.  
  18183.  Sample Program
  18184.  --------------
  18185.  
  18186.  #include <stdio.h>
  18187.  void main (void)
  18188.  {
  18189.     unsigned char x, y;
  18190.     x = 0;
  18191.     y = 255;
  18192.  
  18193.     if (x != (~y))
  18194.         printf ("y is not a complement of x\n");
  18195.     else
  18196.         printf ("y is a complement of x\n");
  18197.  }
  18198.  
  18199.  Response:
  18200.  
  18201.  The code generated in this case is correct. The Microsoft C language
  18202.  reference guide clearly states that operands of unsigned character
  18203.  type are promoted to unsigned integer type when using arithmetic
  18204.  operators. Refer to Point 5, Page 116, in the "Microsoft C for the
  18205.  MS-DOS Operating System: Language Reference."
  18206.  
  18207.  For this sample code to work as you intended, cast the "~y" as
  18208.  unsigned character, as follows:
  18209.  
  18210.     if (x != (unsigned char)(~y))
  18211.         printf ("y is not a complement of x\n");
  18212.     else
  18213.         printf ("y is a complement of x\n");
  18214.  
  18215.  
  18216.  415. Can't Take Address of Frame Variable in DLL (SS!=DS)
  18217.  
  18218.  Product Version(s): 5.10
  18219.  Operating System:   OS/2
  18220.  Flags: ENDUSER | SR# G890605-19757
  18221.  Last Modified: 25-JUL-1989    ArticleIdent: Q45584
  18222.  
  18223.  Question:
  18224.  
  18225.  In my .DLL, whenever I take the address of an automatic variable, the
  18226.  compiler issues the following warning:
  18227.  
  18228.     "address of frame variable taken, DS != SS"
  18229.  
  18230.  Whenever the DLL is called, it causes a GP fault. What is causing this
  18231.  problem and how do I correct it?
  18232.  
  18233.  When I added "NONSHARED" to the DATA directive in the .DEF file, the
  18234.  GP trapping stopped. Why did the trapping stop?
  18235.  
  18236.  Response:
  18237.  
  18238.  If you're using small or medium memory model, your pointers are
  18239.  2-byte pointers, which contain only the offset of the variable into
  18240.  the data segment.
  18241.  
  18242.  In compact, large, and huge models, pointers are 4 bytes, containing
  18243.  both a segment and an offset.
  18244.  
  18245.  When a .DLL is executing, it uses your stack (normally in your
  18246.  data segment) and the .DLL's default data segment. Thus, you must
  18247.  compile with /Au or /Aw, telling the compiler that it should not
  18248.  assume (as it normally does) that DS (the default data segment
  18249.  selector) and SS (the current stack segment selector) are the same.
  18250.  
  18251.  All near (2-byte) pointers are assumed to be relative to current DS.
  18252.  When you take the address of a frame (automatic) variable, this
  18253.  address is relative to SS. When SS == DS, as is the usual case, this
  18254.  is not a problem. However, it does cause problems in .DLLs, where SS
  18255.  cannot be equal to DS.
  18256.  
  18257.  There is no way to take a near address of a stack variable when
  18258.  DS!=SS. You do have several alternatives, however:
  18259.  
  18260.  1. Change to compact, large, or huge model. Since the pointers are far
  18261.     pointers, you'll be able to represent the address properly. In
  18262.     addition, all the run-time library functions accept such far
  18263.     pointers.
  18264.  
  18265.  2. Use a far pointer to hold the address. You can do this without
  18266.     changing memory models. This method has the advantage that the only
  18267.     pointer accesses that are slowed are the individual far pointers
  18268.     used to access the stack. The disadvantage is that most small and
  18269.     medium model library routines do not support far pointers, so
  18270.     you must either avoid those routines or copy the far data into
  18271.     the default data segment before calling the routine. Please note
  18272.     that this is only necessary with routines that accept pointers;
  18273.     routines that accept variables by value aren't affected because the
  18274.     value of the expression doesn't change when the pointer size does.
  18275.     It is strongly recommended that you use prototypes and new-style
  18276.     declarations for ALL your functions to prevent errors.
  18277.  
  18278.  3. Rework the code to avoid the need for taking the address of frame
  18279.     variables.
  18280.  
  18281.  The reason the trapping seems to stop when you changed the .DEF file
  18282.  probably has more to do with the sizes of the segments involved -- in
  18283.  one case, the address generated was larger than the maximum for that
  18284.  segment; in the other, it happened not to be. In each case, the
  18285.  address was wrong because the compiler used DS rather than SS.
  18286.  Therefore, changing the data directive in the .DEF file covered up but
  18287.  did not correct the error.
  18288.  
  18289.  .DLL's which use the C Runtime Library **ALWAYS** use NONSHARED
  18290.  default data and instance initialization.  Instance initialization is
  18291.  specified in the LIBRARY statement of the .DEF file.
  18292.  
  18293.  
  18294.  416. Why There's a 128K Limit on Some Huge Arrays and halloc()s
  18295.  
  18296.  Product Version(s): 5.10   | 5.10
  18297.  Operating System:   MS-DOS | OS/2
  18298.  Flags: ENDUSER | S_QuickC S_QuickASM
  18299.  Last Modified: 21-AUG-1989    ArticleIdent: Q45705
  18300.  
  18301.  Question:
  18302.  
  18303.  Why am I limited to allocating 128K with halloc() or a huge array
  18304.  unless the size of the elements I am using is a power of 2?
  18305.  
  18306.  Response:
  18307.  
  18308.  With huge pointers and arrays, the Microsoft C Compiler produces
  18309.  32-bit pointer arithmetic only when accessing whole elements. Only the
  18310.  16-bit offset of a pointer is used when accessing the individual
  18311.  members of elements. This technique is used in the interest of speed
  18312.  and smaller code size. However, it assumes that elements do not extend
  18313.  from the end of one segment into the beginning of the next. When
  18314.  crossing a 64K segment boundary, elements must end evenly with the end
  18315.  of that segment. The following diagram illustrates the conditions
  18316.  necessary for huge pointers and arrays:
  18317.  
  18318.                           Seg1 Seg2
  18319.       Segment 1               FFFF 0000               Segment 2
  18320.       ----------------------------+----------------------------
  18321.      ......| Elem | Elem  | Elem  + Elem  | Elem  | Elem  |.....
  18322.      ......| X     | X+1  | X+2   + X+3   | X+4   | X+5   |.....
  18323.       ----------------------------+----------------------------
  18324.                                   ^ Elements must not cross
  18325.                     a segment boundary.
  18326.  
  18327.  If an element's size is not a power of 2, an array of that element
  18328.  will not fit evenly into a 64K segment. This is the root of the 128K
  18329.  limitation. To avoid breaking an element across a segment boundary in
  18330.  this case, extra space is left at the beginning of the first segment,
  18331.  pushing the entire array upwards in memory so that the element before
  18332.  the one that would have spanned the segment boundary ends exactly at
  18333.  the segment ending. The element that would have spanned the segment
  18334.  boundary is pushed to the beginning of the second segment.
  18335.  
  18336.  If the allocated elements do not fit evenly into a segment, there can
  18337.  be only one segment boundary onto which they fall evenly. The function
  18338.  halloc() uses the element size it is passed to calculate and return a
  18339.  pointer with an offset that results in the allocated elements falling
  18340.  evenly on this boundary. The following diagram demonstrates the way
  18341.  this is done and what can happen at the end of the second segment:
  18342.  
  18343.          Segment 1                     Segment 2
  18344.          0000           FFFF 0000           FFFF
  18345.       +----------------------+-------------------+
  18346.       +Pad |Elem |Elem |Elem +Elem |Elem |Elem | +
  18347.       +----------------------+-------------------+
  18348.        ^   ^                                   ^
  18349.        ^   ^                                   Next element will not fall
  18350.        ^   ^                                   on segment bounds.
  18351.        ^   ^
  18352.        ^   Offset returned to allow elements to fall on segment bounds.
  18353.        ^
  18354.        Padding area used to force element boundary to fall on segment
  18355.        boundary
  18356.  
  18357.  These restrictions should also be considered when allocating memory
  18358.  for very large elements. For example, a request for three 33K
  18359.  structures will fail. Two of the structures could be allocated, but
  18360.  since each would go into a separate segment, neither of the segments
  18361.  would contain enough space for the third element.
  18362.  
  18363.  
  18364.  417. L2002 When Linking Small Model Main with Other Memory Models
  18365.  
  18366.  Product Version(s): 5.10   | 5.10
  18367.  Operating System:   MS-DOS | OS/2
  18368.  Flags: ENDUSER | S_QuickC
  18369.  Last Modified: 14-AUG-1989    ArticleIdent: Q45710
  18370.  
  18371.  An attempt to link a module that has been compiled in the small memory
  18372.  model with a module compiled in the medium or large memory model
  18373.  produces the following error:
  18374.  
  18375.     L2002: fixup overflow
  18376.  
  18377.  The cause, in this particular case, of the "fixup overflow" error
  18378.  message is not documented in the C Version 5.10 "CodeView and
  18379.  Utilities, Microsoft Editor, Mixed-Language Programming Guide" on Page
  18380.  366.
  18381.  
  18382.  Normally, you should NOT link programs that contain different memory
  18383.  models. All modules should be compiled using the same memory model.
  18384.  (It is possible to use the "near" and "far" keywords to produce
  18385.  mixed-model programs, but this is tricky and usually doesn't give much
  18386.  performance gain.)
  18387.  
  18388.  If the following module, MOD1.C
  18389.  
  18390.      #include<stdio.h>
  18391.  
  18392.      void main(void);
  18393.  
  18394.      void main()
  18395.      {
  18396.          printf(" module 1 \n");
  18397.          mod2();
  18398.      }
  18399.  
  18400.  is linked with the module, MOD2.C
  18401.  
  18402.      #include<stdio.h>
  18403.  
  18404.      void mod2(void);
  18405.  
  18406.      void mod2()
  18407.      {
  18408.          printf(" module 2 \n");
  18409.      }
  18410.  
  18411.  in various memory models, the following results occur:
  18412.  
  18413.      Memory Model      Result
  18414.      ------------      ------
  18415.      MOD1  | MOD2
  18416.      ------|-----
  18417.            |
  18418.       /AS  | /AM       L2002 : fixup overflow
  18419.            |
  18420.       /AS  | /AL       L2002 : fixup overflow
  18421.            |
  18422.       /AM  | /AS       Links, hangs on run
  18423.            |
  18424.       /AM  | /AL       Executes normally
  18425.            |
  18426.       /AL  | /AS       Links, hangs on run
  18427.            |
  18428.       /AL  | /AM       Links, prints trash for MOD2 on run
  18429.  
  18430.  
  18431.  418. Typographical Error in ALMUL.ASM of C Library Source
  18432.  
  18433.  Product Version(s): 5.00 5.10 | 5.10
  18434.  Operating System:   MS-DOS    | OS/2
  18435.  Flags: ENDUSER | H_MASM docerr
  18436.  Last Modified: 13-SEP-1989    ArticleIdent: Q45763
  18437.  
  18438.  In the "Microsoft C Run-Time Library Source Routines" for C Version
  18439.  5.00 or C 5.10, Line 28 of the file ALMUL.ASM in the \HELPER directory
  18440.  contains a typographical error. The incorrect statement reads as
  18441.  follows:
  18442.  
  18443.     assume ds,code
  18444.  
  18445.  The statement should read as follows:
  18446.  
  18447.     assume ds,data
  18448.  
  18449.  Since no data is defined or referenced in the original ALMUL.ASM, the
  18450.  typographical error does not cause problems in the C library. However,
  18451.  if you purchased the C library source code from the end user sales
  18452.  department, defined and referenced data in ALMUL.ASM, and attempted to
  18453.  assemble the modified ALMUL.ASM with MASM, you receive the following
  18454.  error:
  18455.  
  18456.     error A2068: Cannot address with segment register
  18457.  
  18458.  Correcting the error in ALMUL.ASM, as noted above, corrects the
  18459.  problem.
  18460.  
  18461.  
  18462.  419. Using DosExecPgm() After Changing PATH Environment Variable
  18463.  
  18464.  Product Version(s): 5.10
  18465.  Operating System:   OS/2
  18466.  Flags: ENDUSER |
  18467.  Last Modified: 25-JUL-1989    ArticleIdent: Q45904
  18468.  
  18469.  Question:
  18470.  
  18471.  I use the C 5.10 run-time putenv() function to change my PATH
  18472.  environment variable. I then use the OS/2 DosExecPgm() API call to
  18473.  start an executable that lies on that path. DosExecPgm() fails to
  18474.  execute the process, giving me a return code indicating that the file
  18475.  could not be found. I try the run-time spawnlp() function and it works
  18476.  correctly. What is the problem? How can I get DosExecPgm() to work?
  18477.  
  18478.  Response:
  18479.  
  18480.  The C run-time startup code copies the environment table into DGROUP.
  18481.  The putenv() run-time function modifies this copy of the environment.
  18482.  Other C run-time functions, including spawnlp(), will use this copy of
  18483.  the environment. So, when you alter your path variable
  18484.  
  18485.     putenv( "PATH=d:\\whack" );
  18486.  
  18487.  and look at it
  18488.  
  18489.      Path = getenv( "PATH" );
  18490.  
  18491.  you see that Path does indeed point to the new path. However, then
  18492.  using an OS/2 API call to check the path variable
  18493.  
  18494.     DosScanEnv( "PATH", &Path );
  18495.  
  18496.  reveals that the path is unchanged. This is because the API functions
  18497.  deal with the original environment table, not the copy in DGROUP.
  18498.  DosExecPgm() is no exception, meaning that the original PATH
  18499.  environment variable will be used rather than the altered copy.
  18500.  
  18501.  In order to perform a DosExecPgm() of a process that is not on the
  18502.  original search path but is known to be on another search path, you
  18503.  may wish to use the DosSearchPath() function in conjunction with
  18504.  DosExecPgm(), in the following manner:
  18505.  
  18506.  #define INCL_DOS
  18507.  
  18508.  #include <os2.h>
  18509.  #include <stdio.h>
  18510.  
  18511.  void main( void );
  18512.  
  18513.  void main()
  18514.  {
  18515.      RESULTCODES    ResCodes;
  18516.      char           Fail[256];
  18517.      USHORT         ret;
  18518.      char           Pgm[256];
  18519.  
  18520.      DosSearchPath( SEARCH_CUR_DIRECTORY,    // Start with cur dir
  18521.                     "d:\\;c:\\;b:\\whack",   // Search this path
  18522.                     "off.exe",               // For off.exe
  18523.                     Pgm,                     // Put result path here
  18524.                     256 );                   // It's 256 bytes long
  18525.  
  18526.      printf( "Pgm path: %s\n", Pgm );
  18527.  
  18528.      ret = DosExecPgm( Fail,
  18529.                        256,
  18530.                        0,
  18531.                        NULL,
  18532.                        0,
  18533.                        &ResCodes,
  18534.                        Pgm );
  18535.  
  18536.      printf( "DosExecPgm says: %u\n", ret );
  18537.      printf( "Fail: %s\n", Fail );
  18538.  }
  18539.  
  18540.  This program uses DosSearchPath() to generate a full path to
  18541.  "off.exe". Each directory in the path passed to DosSearchPath() will
  18542.  be searched. In this case the current directory will be searched
  18543.  first, because of the SEARCH_CUR_DIRECTORY flag.
  18544.  
  18545.  
  18546.  420. Unresolved Externals Using OS/2 Functions and INCL_NOCOMMON
  18547.  
  18548.  Product Version(s): 5.10
  18549.  Operating System:   OS/2
  18550.  Flags: ENDUSER |
  18551.  Last Modified: 25-JUL-1989    ArticleIdent: Q45946
  18552.  
  18553.  If you are using OS/2 functions and getting "unresolved external"
  18554.  messages at link time even though OS2.H is included, check for a
  18555.  definition of the manifest constant INCL_NOCOMMON. The definition of
  18556.  this constant excludes any function group that is not explicitly
  18557.  included by the definition of another manifest constant.
  18558.  
  18559.  For example, to include the OS/2 system functions (DOS) and exclude
  18560.  all others, the following two statements must exist in the source
  18561.  code:
  18562.  
  18563.     #define INCL_NOCOMMON
  18564.     #define INCL_DOS
  18565.  
  18566.  Look closely at the "unresolved external" message. If the compiler has
  18567.  prepended an underscore to the function name, then the prototype is
  18568.  not being included. All OS/2 functions are defined with a PASCAL
  18569.  calling sequence. Therefore, there should never be an underscore
  18570.  prepended to the function name.
  18571.  
  18572.  As a quick test, remove the INCL_NOCOMMON statement from the code and
  18573.  recompile. If the program compiles and links without the INCL_NOCOMMON
  18574.  statement, then you have only to determine which manifest constant
  18575.  correctly includes the function group that includes the function in
  18576.  question.
  18577.  
  18578.  As an alternative, compiling at warning level three generates a "no
  18579.  prototype given" warning for the function if the function prototype is
  18580.  being excluded by the INCL_NOCOMMON statement. If this is the case,
  18581.  determine which manifest constant will include the function prototype,
  18582.  and define it along with the INCL_NOCOMMON statement.
  18583.  
  18584.  A comprehensive listing of these manifest constants can be found in
  18585.  the "Microsoft OS/2 Programmer's Reference," Volume #1, Pages 41-44.
  18586.  
  18587.  
  18588.  421. fopen Will Set errno Values
  18589.  
  18590.  Product Version(s): 5.10   | 5.10
  18591.  Operating System:   MS-DOS | OS/2
  18592.  Flags: ENDUSER | docerr
  18593.  Last Modified: 18-SEP-1989    ArticleIdent: Q46024
  18594.  
  18595.  Question:
  18596.  
  18597.  The "Microsoft C 5.10 Optimizing Compiler Run-Time Library Reference"
  18598.  manual indicates that open and sopen will set errno values. The fopen
  18599.  documentation on Pages 274-275 does not explicitly state that fopen
  18600.  will set errno. Will fopen set errno?
  18601.  
  18602.  Response:
  18603.  
  18604.  Yes, fopen will set errno values. Internally, fopen calls the same
  18605.  low-level routines that open and sopen call. These routines cause
  18606.  errno to be set.
  18607.  
  18608.  For more information, please refer to the documentation for open.
  18609.  
  18610.  
  18611.  422. Modifying P_tmpdir Does Not Change the Operation of tmpnam()
  18612.  
  18613.  Product Version(s): 5.10
  18614.  Operating System:   MS-DOS
  18615.  Flags: ENDUSER | S_QuickC
  18616.  Last Modified: 25-JUL-1989    ArticleIdent: Q46131
  18617.  
  18618.  The functions tmpnam() and tempnam() both state that under certain
  18619.  conditions they create a name that consists of the path prefix defined
  18620.  by the P_tmpdir entry in STDIO.H. This is ambiguous. A more correct
  18621.  way of stating this is that they create a name that consists of a path
  18622.  prefix to the root of the current drive; this is also what P_tmpdir is
  18623.  defined as. Under C Version 5.10 and QuickC Version 2.00, P_tmpdir is
  18624.  defined as the root directory on the default drive, which is where the
  18625.  created name would reside. However, any modification of P_tmpdir in
  18626.  STDIO.H does not change the filename created.
  18627.  
  18628.  It states on Page 611 of the "Microsoft C for the MS-DOS Operating
  18629.  System Run-Time Library Reference" that changing the definition of
  18630.  P_tmpdir or L_tmpnam does not change the operation of tmpnam(). Nor
  18631.  does it change the operation of tempnam(). These two defines are only
  18632.  provided for XENIX/UNIX portability. The two functions tmpnam() and
  18633.  tempnam() do not make any use of these two defines.
  18634.  
  18635.  
  18636.  423. Typedef of Function Pointer with _loadds Fails
  18637.  
  18638.  Product Version(s): 5.10   | 5.10
  18639.  Operating System:   MS-DOS | OS/2
  18640.  Flags: ENDUSER | SR# G890616-20706
  18641.  Last Modified: 11-SEP-1989    ArticleIdent: Q46270
  18642.  
  18643.  Question:
  18644.  
  18645.  I have the following typedef declaration:
  18646.  
  18647.  typedef  void far _loadds pascal MYFUNC(void);
  18648.  typedef  MYFUNC  far *PMYFUNC;
  18649.  
  18650.  The second typedef gives a compiler warning (at -W3 level):
  18651.  
  18652.     Warning C4105: 'PMYFUNC' : code modifiers only on function
  18653.     or pointer to function
  18654.  
  18655.  How can I avoid the warning?
  18656.  
  18657.  Response:
  18658.  
  18659.  This compiler does not handle this situation properly.
  18660.  
  18661.  One solution is to use a macro as shown below:
  18662.  
  18663.      #define FN_FLP far _loadds pascal
  18664.  
  18665.      void FN_FLP myfunc1();
  18666.  
  18667.      void (FN_FLP *pmyfunc1)();
  18668.  
  18669.  This isn't as attractive as a typedef, but it does help.
  18670.  
  18671.  Another way to work around the problem is to put the definition of the
  18672.  function in a different source file than the calls, leaving the
  18673.  _loadds keyword in the function definition but taking it out of the
  18674.  declarations. Since _loadds does not affect the calling sequence, this
  18675.  process should not cause additional problems.
  18676.  
  18677.  Note: Be sure to check your generated code.
  18678.  
  18679.  Microsoft is researching this problem and will post new information as
  18680.  it becomes available.
  18681.  
  18682.  
  18683.  424. Compiler Options for Intel 80x86 Processors
  18684.  
  18685.  Product Version(s): 5.00 5.10 | 5.00 5.10
  18686.  Operating System:   MS-DOS    | OS/2
  18687.  Flags: ENDUSER |
  18688.  Last Modified: 14-AUG-1989    ArticleIdent: Q46381
  18689.  
  18690.  The following is extracted from the "Microsoft C Optimizing Compiler
  18691.  User's Guide," Page 81, Section 3.3.10, "Using the 80186, 80188, or
  18692.  80286 Processor (/G0, /G1, /G2)":
  18693.  
  18694.  Options
  18695.  -------
  18696.  
  18697.     /G0 Enables instruction set for 8086/8088 processor (default)
  18698.     /G1 Enables instruction set for 80186/80188 processor
  18699.     /G2 Enables instruction set for 80286 processor
  18700.  
  18701.  If you have an 80186, 80188, or 80286 processor, you can use the /G1
  18702.  or /G2 option to enable the instruction set for your processor. Use
  18703.  /G1 for the 80186 and 80188 processors; use /G2 for the 80286.
  18704.  Although it is usually advantageous to enable the appropriate
  18705.  instruction set, you are not required to do so. If you have an 80286
  18706.  processor, for example, but you want your code to be able to run on an
  18707.  8086, you should not use the 80186/80188 or 80286 instruction sets.
  18708.  
  18709.  The /G0 option enables the instruction set for the 8086/8088
  18710.  processor. You need not specify this option explicitly, since the
  18711.  8086/8088 instruction set is used by default. Programs compiled in
  18712.  this way also run on machines with the 80186, 80188, or 80286
  18713.  processor.
  18714.  
  18715.  Since DOS and existing versions of OS/2 are not 80386 operating
  18716.  systems, Version 5.10 (as well as previous versions) of the C compiler
  18717.  do not offer a /G3 switch for 80386 code generation.
  18718.  
  18719.  
  18720.  425. Spawned Processes Do Not Always Handle Signals Properly
  18721.  
  18722.  Product Version(s): 4.x 5.00 5.10
  18723.  Operating System:   MS-DOS
  18724.  Flags: ENDUSER | S_QuickC
  18725.  Last Modified:  9-AUG-1989    ArticleIdent: Q46383
  18726.  
  18727.  In the following example, the CTRL+C signal is not handled as expected
  18728.  within the spawned process:
  18729.  
  18730.      #include <stdio.h>
  18731.      #include <process.h>
  18732.  
  18733.      void main( void )
  18734.      {
  18735.          int err;
  18736.  
  18737.          err = system( "TYPE TEST.TXT | MORE" );
  18738.  
  18739.          printf( "Return from system: %d\n", err );
  18740.      }
  18741.  
  18742.  If CTRL+C is pressed while the file is being typed, temporary files
  18743.  used by MORE to emulate pipes are left in the root of the current
  18744.  drive. The return value from the system does not indicate any
  18745.  problems.
  18746.  
  18747.  This is a limitation of MS-DOS and the way child processes handle
  18748.  certain signals, not a problem with the C compiler. Interrupting an
  18749.  assembly language program that simply calls DOS interrupt 0x4B to
  18750.  spawn "COMMAND /c TYPE TEST.TXT | MORE" gives the same results.
  18751.  
  18752.  
  18753.  426. Where to Find Information on Writing TSRs
  18754.  
  18755.  Product Version(s): 5.10
  18756.  Operating System:   MS-DOS
  18757.  Flags: ENDUSER | SR# G890601-19569
  18758.  Last Modified: 25-JUL-1989    ArticleIdent: Q46734
  18759.  
  18760.  Question:
  18761.  
  18762.  What is the definitive Microsoft reference that describes "the rules"
  18763.  for creating a TSR?
  18764.  
  18765.  Response:
  18766.  
  18767.  Since the DOS environment is so loosely structured, there are no hard
  18768.  and fast rules that guarantee that a TSR will work correctly with any
  18769.  application. The best source for this information is the "MS-DOS
  18770.  Encyclopedia" (published by Microsoft Press). This excellent reference
  18771.  contains a 37-page chapter on TSRs, and other related information on
  18772.  exception handlers and hardware-interrupt service routines. If you
  18773.  take care to write your TSR in the manner described in this reference,
  18774.  you will minimize interactions and other problems.
  18775.  
  18776.  
  18777.  427. Loop Optimization May Cause Improper Type Cast of int
  18778.  
  18779.  Product Version(s): 5.10   | 5.10
  18780.  Operating System:   MS-DOS | OS/2
  18781.  Flags: ENDUSER |
  18782.  Last Modified: 25-JUL-1989    ArticleIdent: Q46735
  18783.  
  18784.  In certain situations, compiling with loop optimization may cause a
  18785.  type cast of an int to a long or unsigned long to produce an incorrect
  18786.  value if the cast precedes a loop. When an int is type cast to a long,
  18787.  the correct conversion sign extends. Thus, a negative integer remains
  18788.  negative. On the other hand, when casting an int to an unsigned long,
  18789.  the correct conversion is to sign extend to long, THEN convert the
  18790.  long to unsigned long. This means a negative integer will be cast to a
  18791.  really huge positive number when cast to an unsigned long. This
  18792.  expected behavior is documented on page 141 of the "Microsoft C 5.1
  18793.  Optimizing Compiler Language Reference." Loop optimization may cause
  18794.  errors in both of these type casts. Disabling loop optimization or
  18795.  rearranging the code corrects the problem.
  18796.  
  18797.  The following program, when compiled with the /Oal or /Ox option,
  18798.  displays this erroneous type casting. In the third assignment
  18799.  statement, -31536 is cast to a long and assigned to lNum. The result
  18800.  should still be -31536, but lNum ends up being 34000. The fourth
  18801.  assignment statement casts this same number to an unsigned long and
  18802.  assigns it to ulNum. The expected result, as described above, is the
  18803.  huge positive number 4294935760, but the value assigned to ulNum is
  18804.  again 34000.
  18805.  
  18806.  Program Sample
  18807.  --------------
  18808.  
  18809.  #include <stdio.h>
  18810.  
  18811.  void main(void)
  18812.  {
  18813.     int iNum;
  18814.     unsigned uNum;
  18815.     long lNum;
  18816.     unsigned long ulNum;
  18817.  
  18818.          lNum = 34000;
  18819.          printf ("lNum = %ld\n", lNum);
  18820.          iNum = (int) lNum;
  18821.          printf ("iNum = (int) lNum = %d \n", iNum);
  18822.          lNum = (long) iNum;
  18823.          printf ("lNum = (long) iNum = %ld \n", lNum);
  18824.          ulNum = (unsigned long) iNum;
  18825.          printf ("ulNum = (unsigned long) iNum = %lu \n", ulNum);
  18826.  
  18827.          for (lNum = 0L; lNum < 17 ; lNum += 1)
  18828.                 ;
  18829.          printf ("%s", "done");
  18830.  }
  18831.  
  18832.  The following is the program output:
  18833.  
  18834.  lNum = 34000                                <== Correct
  18835.  iNum = (int) lNum = -31536                  <== Correct
  18836.  lNum = (long) iNum = 34000                  <== WRONG! (should be -31536)
  18837.  ulNum = (unsigned long) iNum = 34000        <== WRONG! (should be 4294935760)
  18838.  done
  18839.  
  18840.  
  18841.  428. Mixed-Model Programming and long int Helper Library Routines
  18842.  
  18843.  Product Version(s): 5.10
  18844.  Operating System:   MS-DOS
  18845.  Flags: ENDUSER | SR# G890606-19866
  18846.  Last Modified: 25-JUL-1989    ArticleIdent: Q46738
  18847.  
  18848.  Question:
  18849.  
  18850.  I notice that the Microsoft C Optimizing Compiler Version 5.10
  18851.  implicitly generates calls to "helper" routines in to handle long
  18852.  integer arithmetic for operations such as division, left-shift,
  18853.  right-shift, etc.
  18854.  
  18855.  I see a problem in situations such as the following:
  18856.  
  18857.  My program is compiled in small model, so all code and data pointers
  18858.  are near. However, I explicitly declare a far pointer to a long
  18859.  integer, and then I perform a left-shift on this long integer.
  18860.  
  18861.  Won't the library routines be expecting near pointers to data and,
  18862.  therefore, fail?
  18863.  
  18864.  Response:
  18865.  
  18866.  The compiler is aware of this mixed-model programming issue and
  18867.  generates appropriate calls to ensure that the helper routines don't
  18868.  make the wrong assumption as to near versus far pointers.
  18869.  
  18870.  To demonstrate this, consider the following test program:
  18871.  
  18872.  long lNear;                     /* this resides in DGROUP */
  18873.  long far lFar;                  /* this goes in a FAR_BSS segment */
  18874.  
  18875.  void main(void);
  18876.  
  18877.  void main(void)
  18878.  {
  18879.      long lStack;                /* this goes in SS, part of DGROUP */
  18880.  
  18881.      lNear = 30000;
  18882.      lFar  = 15000;
  18883.      lNear <<=4;                 /* force call to helper routines */
  18884.      lFar <<= 4;
  18885.      lStack = lNear + lFar;
  18886.      lStack <<= 4;
  18887.  
  18888.  }
  18889.  
  18890.  The above comments point to the salient points of this test. There are
  18891.  three long variables, one in DGROUP, one in a far segment, and one on
  18892.  the stack. The compiler is asked to left-shift the near and far longs
  18893.  by 4 bits to force a call to the helper routines. Some of the compiled
  18894.  code generated by the above source is shown in the following:
  18895.  
  18896.  ...
  18897.  
  18898.  EXTRN   __acrtused:ABS
  18899.  EXTRN   __chkstk:NEAR
  18900.  EXTRN   __aNNalshl:NEAR
  18901.  EXTRN   __aNFalshl:NEAR
  18902.  _BSS      SEGMENT
  18903.  COMM NEAR       _lNear: BYTE:    4
  18904.  COMM FAR        _lFar:  BYTE:    4
  18905.  
  18906.  ...
  18907.  
  18908.  ;|***     lNear <<=4;
  18909.  ; Line 12
  18910.          *** 000029      b0 04        mov     al,4
  18911.          *** 00002b      50           push    ax
  18912.          *** 00002c      b8 00 00     mov     ax,OFFSET DGROUP:_lNear
  18913.          *** 00002f      50           push    ax
  18914.          *** 000030      e8 00 00     call    __aNNalshl
  18915.  ;|***     lFar <<= 4;
  18916.  ; Line 13
  18917.          *** 000033      b0 04        mov     al,4
  18918.          *** 000035      50           push    ax
  18919.          *** 000036      b8 00 00     mov     ax,OFFSET _lFar
  18920.          *** 000039      ba 00 00     mov     dx,SEG _lFar
  18921.          *** 00003c      52           push    dx
  18922.          *** 00003d      50           push    ax
  18923.          *** 00003e      e8 00 00     call    __aNFalshl
  18924.  
  18925.  Note that even though this program compiled in small model, it created
  18926.  a far segment (FAR_BSS), and it put lFar in it with the declaration
  18927.  "COMM FAR _lFar: Byte: 4". Note also the difference between how it
  18928.  left-shifted the lNear variable (__aNNalshl) versus the way it shifted
  18929.  the lFar variable (__aNFalshl). The routine __aNNalshl is for small
  18930.  model (near code pointer plus near data pointer), whereas __aNFalshl
  18931.  is compact model (near code pointer plus far data pointer); this makes
  18932.  complete sense for the mixed-model program.
  18933.  
  18934.  To summarize, the compiler knows about these near/far dependencies
  18935.  between source code and library routines, and puts in requests for the
  18936.  appropriate routines even if you're in a memory model that wouldn't
  18937.  normally use them (in this case, you wouldn't normally generate a call
  18938.  to __aNFalshl in small model).
  18939.  
  18940.  
  18941.  429. Possible Cause for Slow Stream I/O
  18942.  
  18943.  Product Version(s): 5.10
  18944.  Operating System:   MS-DOS
  18945.  Flags: ENDUSER | S_QuickC
  18946.  Last Modified: 25-JUL-1989    ArticleIdent: Q46741
  18947.  
  18948.  Question:
  18949.  
  18950.  I have an application program that does intensive file manipulation
  18951.  with the stream level I/O routines. Normally it works very fast, but
  18952.  lately the file operations have become increasingly slower and now it
  18953.  can take several minutes to process a single file. What causes this
  18954.  time delay in the stream I/O routines and how can I prevent it?
  18955.  
  18956.  Response:
  18957.  
  18958.  The stream level I/O routines inherit their speed and flexibility from
  18959.  the buffering system they use. Upon opening a file with the fopen
  18960.  function, a file record is created that contains pointers into a
  18961.  stream buffer. This buffer is then allocated (malloc-ed) when the
  18962.  first I/O operation is performed. If there is not enough room in the
  18963.  heap for this buffer allocation, the file operation continues with a
  18964.  buffer size of one character.
  18965.  
  18966.  A stream I/O routine that takes an excessive amount of time is most
  18967.  likely the result of a failure to allocate the 512-byte buffer on the
  18968.  heap (near or far, depending on the memory model). Without this
  18969.  buffer, the I/O routines are extremely slow, requiring disk access for
  18970.  all I/O operations.
  18971.  
  18972.  To get around this problem, you can do one of two things. Reduce the
  18973.  amount of allocation on the heap. Or, change memory models to compact
  18974.  or large (if you are in small or medium). If you change memory models,
  18975.  you may need to use the /Gt switch to push static data out of DGROUP.
  18976.  
  18977.  
  18978.  430. Some Causes of Differences in Floating-Point Results
  18979.  
  18980.  Product Version(s): 5.10
  18981.  Operating System:   MS-DOS
  18982.  Flags: ENDUSER | SR# G890124-10419
  18983.  Last Modified: 25-JUL-1989    ArticleIdent: Q46749
  18984.  
  18985.  This article discusses some reasons why programs might produce
  18986.  different floating-point results when compiled with different compiler
  18987.  options.
  18988.  
  18989.  The program below produces different results when complied using
  18990.  
  18991.     cl -AM -FPi prog.c
  18992.  
  18993.  than when using the following:
  18994.  
  18995.     cl -AM -FPa prog.c
  18996.  
  18997.  Part of the reason for these differences is that /FPa and /FPi
  18998.  generate math routines that work differently. /FPi math emulates the
  18999.  80x87, to the point of actually converting 8-byte doubles to 10-byte
  19000.  internal format and doing the math in internal format. /FPa uses an
  19001.  8-byte format for calculations; therefore, it is less accurate. This
  19002.  often accounts for differences in results.
  19003.  
  19004.  Also of special interest is the fact that the second number printed in
  19005.  the /FPi case is smaller than DBL_MIN, as defined in FLOAT.H. This
  19006.  situation is also correct because DBL_MIN is the smallest possible
  19007.  NORMALIZED value. (Normalized means that the high-order bit of the
  19008.  mantissa is a one.)
  19009.  
  19010.  "Denormals" (numbers where there are zeros in some of the high-order
  19011.  bits of the mantissa), however, can represent numbers "x" in the
  19012.  ranges + DBL_MIN > x > 0 and 0 > x > -DBL_MIN. Although this is an
  19013.  unusual situation, it is not an error. Although it is less precise
  19014.  than a normalized number, a denormal is still more precise than 0
  19015.  (zero) (which is the next best representation). By allowing use of
  19016.  denormal numbers, we make our floating-point result slightly more
  19017.  accurate. The alternate math library (/FPa) represents denormal
  19018.  numbers as 0 (zero).
  19019.  
  19020.  There is a good explanation of floating point exceptions (including
  19021.  the denormal exception, which is always masked) in the FPEXCEPT.DOC
  19022.  file that comes with the C compiler. For more detailed background, see
  19023.  the Intel "80387 Programmer's Reference Manual."
  19024.  
  19025.  Another possible cause of differences in floating-point results is the
  19026.  inclusion or omission of the /Op option. When /Op is omitted, the
  19027.  compiler may skip storing intermediate results as 64-bit objects in
  19028.  memory, leaving them instead in the 80-bit registers of the 80x87 (or
  19029.  emulator package). This increases the speed and accuracy of the
  19030.  calculation. However, this can decrease the consistency of the
  19031.  calculations because other intermediate results may have been stored
  19032.  in 64-bit objects in memory anyway. Including /Op forces all
  19033.  intermediate results to be stored in memory, giving more consistent
  19034.  results. This option is often handy in programs involving complicated
  19035.  floating-point calculations.
  19036.  
  19037.  The program and its output follow:
  19038.  
  19039.  #include <stdio.h>    // START OF PROG.C
  19040.  #include <float.h>
  19041.  
  19042.  main()
  19043.  {
  19044.      double  a,d,c,prod1,prod2;
  19045.  
  19046.      _fpreset();
  19047.      a=9.5788979e-283;
  19048.      b=8.050847e-1;
  19049.      c=9.5588526e-28;
  19050.  
  19051.      prod1=a*b;
  19052.      printf("\n product1 = %1.15le \n",prod1);
  19053.      prod2=c*prod1;
  19054.      printf("\n product2 = %1.15le \n",prod2);
  19055.  
  19056.  }  // END OF PROG.C
  19057.  
  19058.   // RESULTS OBTAINED USING CL -AM -FPi  PROG.C
  19059.  
  19060.   product1 = 7.711824142152130e-283
  19061.  
  19062.   product2 = 7.371619025195353e-310 // This value is less than DBL_MIN
  19063.  
  19064.   // RESULTS OBTAINED USING CL -AM -FPa PROG.C
  19065.  
  19066.   product1 = 7.711824142152130e-283
  19067.  
  19068.   product2 = 0.000000000000000e+000
  19069.  
  19070.  
  19071.  431. Using C Run-Time Library Functions in .DLLs
  19072.  
  19073.  Product Version(s): 5.10
  19074.  Operating System:   OS/2
  19075.  Flags: ENDUSER | SR# G890705-21975
  19076.  Last Modified: 25-JUL-1989    ArticleIdent: Q46773
  19077.  
  19078.  Question:
  19079.  
  19080.  In a .DLL, what C standard library functions are usable?
  19081.  
  19082.  Also, one reference mentions special re-entrant libraries for use in
  19083.  .DLLs. Is that correct, and if so, how do you get at them? Is there
  19084.  some place where this information is documented?
  19085.  
  19086.  Response:
  19087.  
  19088.  There's been a lot of confusion about the proper way to write .DLLs
  19089.  because what was legal and what's not legal has changed at least once
  19090.  during the lifetime of the OS/2 SDK.
  19091.  
  19092.  In the past, there were restrictions on which library functions you
  19093.  could use and how you could use them. These restrictions have been
  19094.  removed because we've created several specially-modified libraries
  19095.  that can be used freely in .DLLs. All library functions can be called.
  19096.  Any serialization needed is handled by the library.
  19097.  
  19098.  The proper way to create .DLLs is outlined in the file MTDYNA.DOC,
  19099.  which is included with the C 5.10 compiler. There are also examples
  19100.  included with the compiler that you can compile and modify. If you are
  19101.  developing for OS/2 1.10, instead of OS/2 1.00, with the OS/2 1.10
  19102.  Software Development Kit or Tool Kit, use the OS/2 1.10 library
  19103.  OS2.LIB in place of the OS/2 1.00 library DOSCALLS.LIB. Also make sure
  19104.  to include the OS/2 1.10 include files before, or instead of, the C
  19105.  5.10 regular and multi-thread include files with the same names, such
  19106.  as OS2.H and BSE.H. These C 5.10 OS/2 API-related include files are
  19107.  for OS/2 1.00.
  19108.  
  19109.  Note: There are two very important details about writing your .DEF
  19110.  file that MTDYNA.DOC doesn't mention:
  19111.  
  19112.  1. You MUST use a DATA MULTIPLE NONSHARED statement for any .DLL that
  19113.     uses the C run-time library because each process that uses the .DLL
  19114.     needs its .DLL to have a separate data area. Otherwise, multiple
  19115.     instances of the .DLL will corrupt each other's C run-time library
  19116.     static data.
  19117.  
  19118.  2. You also MUST use LIBRARY INITINSTANCE in any .DLL that calls the
  19119.     C run-time library because each instance of the .DLL must have its
  19120.     run-time library data area initialized separately.
  19121.  
  19122.  Aside from these two details and the new OS/2 1.10 library and header
  19123.  files, MTDYNA.DOC is an excellent guide for writing .DLLs.
  19124.  
  19125.  
  19126.  432. _setvideomode Resets the Palette
  19127.  
  19128.  Product Version(s): 5.10
  19129.  Operating System:   MS-DOS
  19130.  Flags: ENDUSER | S_QuickC _remapallpalette _remappalette
  19131.  Last Modified: 25-JUL-1989    ArticleIdent: Q46792
  19132.  
  19133.  The Microsoft C function _setvideomode resets the palette to the
  19134.  default palette colors each time it is called. Therefore, remapping
  19135.  the color palette in C lasts only as long as the video mode remains
  19136.  active.
  19137.  
  19138.  
  19139.  433. Q & A on MS Recommendation of Glockenspiel C++ and CommonView
  19140.  
  19141.  Product Version(s): 5.10
  19142.  Operating System:   MS-DOS
  19143.  Flags: ENDUSER | SR# G890705-21998 plus plus
  19144.  Last Modified: 26-JUL-1989    ArticleIdent: Q46836
  19145.  
  19146.  The following questions and answers concern the use of Glockenspiel
  19147.  C++:
  19148.  
  19149.  Q. Does Microsoft recommend the Glockenspiel C++ and CommonView?
  19150.  
  19151.  A. Microsoft has included their advertising literature in our C
  19152.  Version 5.10 package and has mentioned them in the new languages
  19153.  newsletter, which was sent to all registered users. Glockenspiel's C++
  19154.  is a preprocessor, which generates C 5.10 code from your C++ source
  19155.  program. (You then use Microsoft C 5.10 to compile this code.) This
  19156.  C++ product is currently the only way to use C++ while retaining the
  19157.  sophisticated code generation and tool set of Microsoft C. It is ideal
  19158.  for Microsoft customers who want to use C++ today.
  19159.  
  19160.  CommonView is a C++ object library, which makes programming for
  19161.  graphical user interfaces, including Windows, easier. This is also the
  19162.  only product of its type on the market today that is compatible with
  19163.  Microsoft C.
  19164.  
  19165.  The products included here are manufactured by vendors independent of
  19166.  Microsoft; we make no warranty, implied or otherwise, regarding these
  19167.  products' performance or reliability.
  19168.  
  19169.  Q. What does Microsoft think about C++? Does Microsoft recommend
  19170.  programming in C++?
  19171.  
  19172.  A. Microsoft has publicly stated that object-oriented programming,
  19173.  including C++, is the way of the future and that it will result in
  19174.  great productivity gains for programmers. We have already introduced
  19175.  object-oriented extensions in our new QuickPascal product and have
  19176.  announced that we are working on an implementation of C++ (release
  19177.  date is unknown). We think that this is very important technology and
  19178.  that it will make possible the sophisticated systems of tomorrow.
  19179.  
  19180.  Since C++ is going to be so important in the near future, it is
  19181.  certainly wise to start getting experience in it now.
  19182.  
  19183.  Q. Does Microsoft use C++ in-house?
  19184.  
  19185.  A. Microsoft uses a variety of languages in-house including Microsoft C
  19186.  and MASM. Beyond that, it is not possible to comment on which products
  19187.  use what languages.
  19188.  
  19189.  
  19190.  434. Type of Expression "&arrayname" Changes under ANSI C
  19191.  
  19192.  Product Version(s): 5.10   | 5.10
  19193.  Operating System:   MS-DOS | OS/2
  19194.  Flags: ENDUSER | SR# G890706-22068
  19195.  Last Modified: 26-JUL-1989    ArticleIdent: Q46947
  19196.  
  19197.  Question:
  19198.  
  19199.  When I compile the following program
  19200.  
  19201.  1:  void main(void)
  19202.  2:      {
  19203.  3:      char String[10];
  19204.  4:      char *s;
  19205.  5:
  19206.  6:      s = &String;
  19207.  7:      }
  19208.  
  19209.  using Version 5.10 and the command line
  19210.  
  19211.     cl -W3 karma.c
  19212.  
  19213.  the compiler generates the following message:
  19214.  
  19215.     karma.c(6) : warning C4046: '&' on function/array, ignored
  19216.  
  19217.  This is consistent with historical C behavior. However, I understand
  19218.  that ANSI C considers array names to be lvalues. The July 1989 MSJ
  19219.  article "Pointers 101: Understanding and Using Pointers in the C
  19220.  Language" validates this assumption. Does this mean that the "&" in
  19221.  "&String" is no longer benign? Under ANSI C, does this give me (in
  19222.  effect) a pointer to the address of "String"? What is the type and
  19223.  value of the expression "&String"?
  19224.  
  19225.  Response:
  19226.  
  19227.  The 5.10 compiler ignores the "&", so the type of "&String" is the
  19228.  same as "String", which is "pointer to char." This represents common
  19229.  pre-ANSI behavior.
  19230.  
  19231.  ANSI requires that the type of "&String" now be "pointer to array of
  19232.  10 char." The next version of Microsoft C will conform to this
  19233.  requirement.
  19234.  
  19235.  However, aside from type warnings that may occur, this change IS
  19236.  benign because the address generated is identical in either case --
  19237.  the address of the zeroth element of the array. In other words, it
  19238.  will not somehow generate the address of the address -- especially
  19239.  since the address is a constant.
  19240.  
  19241.  
  19242.  435. MSJ 9/88: "Using MSC for TSRs" Omission/TSRs in C Information
  19243.  
  19244.  Product Version(s): 5.10
  19245.  Operating System:   MS-DOS
  19246.  Flags: ENDUSER | SR# G890710-22224
  19247.  Last Modified: 26-JUL-1989    ArticleIdent: Q46948
  19248.  
  19249.  The September 1988 article in Microsoft Systems Journal (MSJ) titled
  19250.  "Using Microsoft C Version 5.1 to Write Terminate-and-Stay-Resident
  19251.  Programs" omits and misstates some important information about writing
  19252.  TSRs. In addition, the example calls BIOS from within a TSR, which is
  19253.  not guaranteed to be safe. Although this article is an excellent
  19254.  introduction to writing TSRs, especially in C, it does not contain all
  19255.  of the needed information. The article on TSRs in the "MS-DOS
  19256.  Encyclopedia" is a much more definitive reference.
  19257.  
  19258.  There are two problems in the article: first, the program calls BIOS
  19259.  functions from within the TSR. Since BIOS is not re-entrant, you can't
  19260.  always call BIOS from within a TSR. Second, it is not good advice to
  19261.  say that it's OK to compile with -AS rather than -Asnw. Unless you're
  19262.  going to switch to your own stack in the TSR, you should always use
  19263.  -Asnw.
  19264.  
  19265.  The article is correct when it says that, in general, you may NOT call
  19266.  DOS functions from within a TSR without taking special precautions.
  19267.  DOS is not re-entrant.
  19268.  
  19269.  Although the MSJ article does prepare you for the concepts you'll need
  19270.  to write TSRs, the best reference is the "MS-DOS Encyclopedia," which
  19271.  has a 40-page chapter on the topic. Among the topics are descriptions
  19272.  of how to safely call BIOS and DOS from within a TSR. The "MS-DOS
  19273.  Encyclopedia" is available in hardcover and paperback from Microsoft
  19274.  Press at (800) 888-3303 and is an exceptionally useful reference book.
  19275.  
  19276.  Programming TSRs in C is a very complicated task. Microsoft is unable
  19277.  to offer assistance beyond the "MS-DOS Encyclopedia" to help you with
  19278.  TSR programming. There are a number of small problems: many library
  19279.  functions call DOS, do stack checks, or make memory allocations (or
  19280.  all three); so they can't be called. However, you can often work
  19281.  around this problem by buying the library source from Microsoft [call
  19282.  (800) 426-9400] and modifying offending routines.
  19283.  
  19284.  A bigger problem is that there is no routine supplied to change the
  19285.  stack from the user's stack to your own. It's not wise to rely on the
  19286.  user's stack being big enough for your needs. To change to your own
  19287.  stack, you'll need an assembly-language subroutine, which may be a
  19288.  part of some function packages for writing TSRs in C.
  19289.  
  19290.  It's a bit easier to program TSRs in assembly language. With assembly
  19291.  language, you know exactly what's going on all the time. This is a big
  19292.  help in debugging. For a TSR that's going to be reliable, you'll need
  19293.  to know exactly what's going on.
  19294.  
  19295.  There are third-party packages that make programming TSRs in C
  19296.  easier and safer. You may want to contact one of the PC programmers'
  19297.  software houses about this.
  19298.  
  19299.  
  19300.  436. VRES Video Modes Have 30 Lines Using Graphics Text Functions
  19301.  
  19302.  Product Version(s): 5.00 5.10
  19303.  Operating System:   MS-DOS
  19304.  Flags: ENDUSER | S_QuickC
  19305.  Last Modified: 15-JAN-1990    ArticleIdent: Q47021
  19306.  
  19307.  When using the Output Text routines in the Microsoft run-time library
  19308.  (Version 5.10 "Microsoft C for the MS-DOS Operating System: Run-Time
  19309.  Library Reference," Pages 54-55), the two graphic modes, _VRES2COLOR
  19310.  and _VRES16COLOR, have 30 text lines by default, due to their
  19311.  increased vertical resolution. All other graphics modes have 25 text
  19312.  lines when using these routines.
  19313.  
  19314.  The following graphics functions are the routines concerned with text
  19315.  placement and output:
  19316.  
  19317.     _displaycursor()
  19318.     _gettextcolor()
  19319.     _gettextposition()
  19320.     _outtext()
  19321.     _settextposition()
  19322.     _settextcolor()
  19323.     _settextwindow()
  19324.     _wrapon()
  19325.  
  19326.  The line numbers stated above are based on the default 8 x 8 font size
  19327.  of the IBM ROM BIOS. Note that when using fonts, the number of text
  19328.  lines in any video mode depends on the height of the font. For
  19329.  information concerning changing from the default font size, see the
  19330.  interrupt 10, function 11 entries in "IBM ROM BIOS," a Microsoft Press
  19331.  book by Ray Duncan.
  19332.  
  19333.  
  19334.  437. Using _pgmptr to Get the Full Path of the Executing Program
  19335.  
  19336.  Product Version(s): 5.10   | 5.10
  19337.  Operating System:   MS-DOS | OS/2
  19338.  Flags: ENDUSER |
  19339.  Last Modified:  8-AUG-1989    ArticleIdent: Q47037
  19340.  
  19341.  Question:
  19342.  
  19343.  On Page Update-23 of the "Version 5.10 Update" to the Microsoft C 5.10
  19344.  Optimizing Compiler, there is a description of the variable _pgmptr.
  19345.  The documentation states that _pgmptr points to a string containing
  19346.  the full pathname of the invoked program, but does not describe how to
  19347.  use it. I can't find _pgmptr in any of the include files. Where is
  19348.  _pgmptr declared and how do I use it?
  19349.  
  19350.  Response:
  19351.  
  19352.  The variable _pgmptr is not defined in an include file. It is declared
  19353.  in CRT0DAT.ASM, which is part of the C start-up code. This code is
  19354.  linked in to any module that contains a main() function. To use
  19355.  _pgmptr, you must first declare it as an external far character
  19356.  pointer, as follows:
  19357.  
  19358.     extern char far *_pgmptr;
  19359.  
  19360.  Since _pgmptr is automatically initialized at start-up to point to the
  19361.  full pathname of the executing program, this declaration is all that
  19362.  is required to make the full pathname available to your program.
  19363.  
  19364.  The following program demonstrates the usage of _pgmptr:
  19365.  
  19366.  #include <stdio.h>
  19367.  
  19368.  extern char far *_pgmptr;
  19369.  
  19370.  void main(void)
  19371.  {
  19372.    printf ("The full path of the executing program is : %Fs\n", _pgmptr);
  19373.  }
  19374.  
  19375.  In OS/2 real mode or DOS 3.x, argv[0] also contains a pointer to the
  19376.  full pathname of the executing program. In OS/2 protected mode,
  19377.  argv[0] contains only the information typed at the command line to
  19378.  invoke the program. Therefore, in OS/2 protected mode, using _pgmptr
  19379.  is the only way to easily access the executing program's full pathname
  19380.  string.
  19381.  
  19382.  
  19383.  438. Best to Avoid C Run-Time Library Routines in TSRs
  19384.  
  19385.  Product Version(s): 5.10
  19386.  Operating System:   MS-DOS
  19387.  Flags: ENDUSER | SR# G890601-19569
  19388.  Last Modified: 30-AUG-1989    ArticleIdent: Q47105
  19389.  
  19390.  Question:
  19391.  
  19392.  I have two questions about using the C run-time library in a TSR
  19393.  (terminate-and-stay-resident program):
  19394.  
  19395.  1. Will I encounter any problems with calling the following routines
  19396.     from a TSR? What about other library routines?
  19397.  
  19398.        _strncmp    __aFFalshr   __chkstk   _sprintf  _free
  19399.        __acrtused  _memcpy      _realloc   _strlen   _malloc
  19400.        _strcmp     __aFFaulshr
  19401.  
  19402.  2. What DOS system calls (INT 21) do the C library references shown
  19403.     above generate? I want to avoid calling DOS because it's not
  19404.     re-entrant.
  19405.  
  19406.  Response:
  19407.  
  19408.  Microsoft does not recommend using standard library routines in TSRs
  19409.  at all, even though they may appear to be safe. The main problem is
  19410.  that although they may be safe in this version of the compiler, they
  19411.  may change in future versions. Microsoft does not support using the
  19412.  run-time code in a TSR.
  19413.  
  19414.  In particular, you can have severe problems with chkstk, sprintf,
  19415.  malloc, realloc, and free. It is likely that the other routines won't
  19416.  present too much of a problem, but without digging through the source
  19417.  and knowing EXACTLY what you're doing, there is no way to be sure.
  19418.  
  19419.  There is, however, an excellent alternative. Microsoft offers the
  19420.  run-time library source for sale. Call our sales number at (800)
  19421.  426-9400 for pricing and to order. With this source, you have almost
  19422.  total control over what your TSR looks like and how it acts. You can
  19423.  inspect each routine you use to ensure that it won't cause any
  19424.  interactions you don't want, and you can modify those routines that
  19425.  do. You're also better insulated against later modifications to the
  19426.  run-time library; since you control the code, you can modify it when
  19427.  you need to. This is by far your best alternative. You'll KNOW what's
  19428.  going on and you'll be able to ensure that you can maintain your
  19429.  applications. The only routines not included in this source are the
  19430.  floating-point and graphics routines.
  19431.  
  19432.  You may be able to find a source for routines written to support TSR
  19433.  programming even though Microsoft does not offer such software. Look
  19434.  for ads in the programmer-oriented PC magazines and/or call some of
  19435.  the programming-oriented software dealers.
  19436.  
  19437.  The run-time source allows you to determine which functions call DOS
  19438.  via INT 21h and which don't. Having the source also allows you to come
  19439.  up with alternative strategies for those functions that make calls.
  19440.  
  19441.  The "MS-DOS Encyclopedia" (published by Microsoft Press) is an
  19442.  excellent source of information about writing TSRs.
  19443.  
  19444.  
  19445.  439. Warning C4051: Data Conversion from Constant to float
  19446.  
  19447.  Product Version(s): 5.10   | 5.10
  19448.  Operating System:   MS-DOS | OS/2
  19449.  Flags: ENDUSER |
  19450.  Last Modified: 25-JUL-1989    ArticleIdent: Q47158
  19451.  
  19452.  Question:
  19453.  
  19454.  Why does the following program cause the C compiler to issue warning
  19455.  C4051 data conversion at warning level 2 or 3?
  19456.  
  19457.     void main(void)
  19458.      {
  19459.        float  num1 = 3.4;
  19460.      }
  19461.  
  19462.  Response:
  19463.  
  19464.  The data conversion results from a type conversion between a float and
  19465.  a double. Num is declared as a float while 3.4 is a constant. Floating
  19466.  point constants have a default type of double. You may eliminate this
  19467.  warning error in one of two ways:
  19468.  
  19469.  1. Declare the constant as a float as follows:
  19470.  
  19471.        float num1 = 3.4f;
  19472.  
  19473.     where the "f", or an "F", following "3.4" indicates that the constant
  19474.     is a 4-byte float instead of an 8-byte double.
  19475.  
  19476.  2. Type cast the constant to a float as follows:
  19477.  
  19478.        float num = (float) 3.4;
  19479.  
  19480.  
  19481.  440. .DEF File Optional Internal Names Not Supported by Implib
  19482.  
  19483.  Product Version(s): 5.10   | 5.10
  19484.  Operating System:   MS-DOS | OS/2
  19485.  Flags: ENDUSER | OPSYS PMWIN BUSLANG
  19486.  Last Modified: 17-AUG-1989    ArticleIdent: Q47225
  19487.  
  19488.  The implib utility does not put the optional internal name of a
  19489.  dynamically linked function into the import library it creates. Implib
  19490.  puts only the entry name of the function (the function name that
  19491.  external modules call) into the import library.
  19492.  
  19493.  The use of optional internal names is supported only by linking with
  19494.  the module definition file (.DEF) that specifies the internal function
  19495.  names (the actual function names in the source file) within a Dynamic
  19496.  Link Library (DLL) for OS/2 or DOS Windows.
  19497.  
  19498.  In a .DEF file, you can optionally specify aliases for the entry
  19499.  points into your DLL as in the following .DEF file statement:
  19500.  
  19501.  EXPORTS
  19502.      ENTRYNAME=INTERNALNAME
  19503.  
  19504.  ENTRYNAME is the name of a DLL routine called by other modules, and
  19505.  the optional INTERNALNAME is the actual name of the function or
  19506.  procedure in the DLL. By default, the INTERNALNAME is the same as the
  19507.  ENTRYNAME, but you may want to provide more meaningful entry names to
  19508.  the users of your DLL in addition to the actual internal function
  19509.  names.
  19510.  
  19511.  The names of dynamically linked functions in a DLL must be specified
  19512.  in either a .DEF file or in an import library, which has a .LIB
  19513.  extension, so that the linker can resolve all references (calls) to
  19514.  the DLL functions. Attempting to link an application that calls DLL
  19515.  functions without an import library or .DEF file results in LINK :
  19516.  error L2029: Unresolved externals: for the DLL function names.
  19517.  
  19518.  Import libraries, consisting of little more than the names of the
  19519.  modules in the DLL and the externally callable functions within the
  19520.  DLL, are created by the implib utility from an existing .DEF file with
  19521.  a command such as the following, which creates the import library
  19522.  "myimport.lib" from the existing module definition file "myfile.def":
  19523.  
  19524.     implib myimport.lib myfile.def
  19525.  
  19526.  Commonly used import libraries for OS/2 are DOSCALLS.LIB for the OS/2
  19527.  1.00 API (Application Program Interface) DLL routines, OS2.LIB for
  19528.  OS/2 1.10, or CRTLIB.LIB for the multi-thread C 5.10 run-time
  19529.  CRTLIB.DLL. The Windows Software Development Kit for creating DOS
  19530.  Windows applications comes with memory model-specific import libraries
  19531.  such as SLIBW.LIB.
  19532.  
  19533.  
  19534.  441. _makepath() and _splitpath Examples Are Incomplete
  19535.  
  19536.  Product Version(s): 5.00 5.10 | 5.00 5.10
  19537.  Operating System:   MS-DOS    | OS/2
  19538.  Flags: ENDUSER | docerr S_QuickC
  19539.  Last Modified: 17-AUG-1989    ArticleIdent: Q47226
  19540.  
  19541.  In the C 5.x "Microsoft C for the MS-DOS Operating System: Run-Time
  19542.  Library Reference" documentation for _makepath (Page 407) and
  19543.  _splitpath (Page 559), the examples do not compile without generating
  19544.  an indirection error. This is due to the variables being declared as
  19545.  pointers. Also, the file should include <stdlib.h>, not <dos.h>. Below
  19546.  is an example of how the file should read to compile on warning level
  19547.  3 without errors.
  19548.  
  19549.  In the QuickC Versions 1.00 and 1.01 "Microsoft QuickC Run-Time
  19550.  Library Reference," the documentation for _makepath (Page 407) and
  19551.  _splitpath (Page 559) also contain an error. The example program
  19552.  declares the ext variable as a 4-byte character array. This should be
  19553.  changed to a 5-byte array as shown below. This second problem appears
  19554.  when the file extension has a three-character extension such as
  19555.  ".doc".
  19556.  
  19557.  The following code should be used in place of the examples for
  19558.  _makepath and _splitpath in the QuickC 1.x run-time documentation as
  19559.  well.
  19560.  
  19561.  #include <dos.h>
  19562.  #include <stdlib.h>
  19563.  #include <stdio.h>
  19564.  
  19565.  void main( void )
  19566.  {
  19567.      char path_buffer [40];
  19568.      char drive [3];
  19569.      char dir [30];
  19570.      char fname [9];
  19571.      char ext [5];
  19572.  
  19573.      _makepath (path_buffer, "d:", "\\src\\test\\", "new","dat");
  19574.      printf("path created with _makepath: %s\n\n", path_buffer);
  19575.  
  19576.      _splitpath (path_buffer, drive, dir, fname, ext);
  19577.      printf("path extracted with _splitpath\n");
  19578.      printf("drive: %s\n", drive);
  19579.      printf("dir: %s\n", dir);
  19580.      printf("fname: %s\n", fname);
  19581.      printf("ext: %s\n", ext);
  19582.  }
  19583.  
  19584.  
  19585.  442. BSEARCH Does Not Find the First Occurrence of Key in the Array
  19586.  
  19587.  Product Version(s): 5.10   | 5.10
  19588.  Operating System:   MS-DOS | OS/2
  19589.  Flags: ENDUSER | docerr S_QuickC
  19590.  Last Modified: 31-AUG-1989    ArticleIdent: Q47234
  19591.  
  19592.  The run-time library function bsearch() is documented on Page 147 in
  19593.  the "Microsoft C for the MS-DOS Operating System: Run-Time Library
  19594.  Reference" as returning a pointer to the first occurrence of key in
  19595.  the array pointed to by base. This may not be true when multiple
  19596.  elements of the array match the key. In the case where multiple
  19597.  elements match the key, bsearch returns a pointer to the first element
  19598.  that it finds, not necessarily the first element of the array that
  19599.  matches the key. This is the proper action for bsearch to take. The
  19600.  documentation should read as follows:
  19601.  
  19602.     Return Value:
  19603.  
  19604.     The bsearch function returns a pointer to the occurrence of key in
  19605.     the array pointed to by base. If there is more than one occurrence
  19606.     of key, the pointer returned by bsearch may point to any of them.
  19607.     If key is not found, the function returns NULL.
  19608.  
  19609.  The behavior occurs because of the nature of the binary search
  19610.  algorithm. If you need to find the first matching element, use the
  19611.  lfind() (linear find) function instead of bsearch(). Note: Linear
  19612.  finds are much slower than binary searches.
  19613.  
  19614.  Below is a sample program that demonstrates this behavior:
  19615.  
  19616.  #include <search.h>
  19617.  #include <string.h>
  19618.  #include <stdio.h>
  19619.  
  19620.  int qcompare();  /* declare a function for qsort's compare   */
  19621.  int bcompare();  /* declare a function for bsearch's compare */
  19622.  
  19623.  main (argc, argv)
  19624.  int argc;
  19625.  char **argv;
  19626.  {
  19627.      char **result;
  19628.      char *key = "Brad";
  19629.      int i;
  19630.  
  19631.      /* Sort using Quicksort algorithm: */
  19632.  
  19633.      qsort((char *) argv, argc, sizeof(char *), qcompare);
  19634.      for (i = 0; i<argc; ++i)                        /* Output sorted list */
  19635.          printf("%s\n", argv[i]);
  19636.  
  19637.      /* Find item that begins with "Brad" using a binary search algorithm: */
  19638.  
  19639.      result = (char **) bsearch((char *) &key, (char *) argv, argc,
  19640.          sizeof(char *), bcompare);
  19641.      if (result)
  19642.          printf("%s found\n", *result);
  19643.      else
  19644.          printf("PATH not found !\n");
  19645.  }
  19646.  
  19647.  int qcompare (arg1, arg2)
  19648.  char **arg1, **arg2;
  19649.  {                      /* Compare all of both strings: */
  19650.      return (strcmp(*arg1, *arg2));
  19651.  }
  19652.  
  19653.  int bcompare (arg1, arg2)
  19654.  char **arg1, **arg2;
  19655.  {                      /* Compare to length of key: */
  19656.      return (strncmp(*arg1, *arg2, strlen(*arg1)));
  19657.  }
  19658.  
  19659.  The program sorts the command line args and then compares them with
  19660.  the key "Brad". If you enter the command line arguments, Brad1 Brad2
  19661.  Doug, you find that the bsearch routine returns Brad2. Note: The
  19662.  number is not checked because the bcompare function checks only the
  19663.  first four characters.
  19664.  
  19665.  Since BSEARCH cuts the array section being searched in half with each
  19666.  check, it finds Brad2 before Brad1. Instead of continuing to search
  19667.  for the first occurrence of Brad (as is documented), it immediately
  19668.  returns with a pointer to Brad2 (which is the proper action).
  19669.  
  19670.  
  19671.  443. scanf Unable to Match Extended Characters in Format String
  19672.  
  19673.  Product Version(s): 5.10   | 5.10
  19674.  Operating System:   MS-DOS | OS/2
  19675.  Flags: ENDUSER | S_QuickC
  19676.  Last Modified:  9-AUG-1989    ArticleIdent: Q47369
  19677.  
  19678.  Note: In this article, the "??" symbol is used to represent an
  19679.  extended ASCII character. Because extended ASCII characters appear
  19680.  differently on many systems, it is unreliable to use a real character.
  19681.  Therefore, whenever you see the "??" symbol, it is meant to represent
  19682.  a character with an ASCII code of 128 to 255.
  19683.  
  19684.  When using the scanf functions (scanf, cscanf, fscanf, sscanf), you
  19685.  may place literal characters in the format string and scanf will read
  19686.  an input string as long as the input string matches these characters
  19687.  in position and value. Once the input string conflicts with the
  19688.  format, scanf terminates. The allowable characters are the standard
  19689.  ASCII values only and attempts to use extended ASCII characters in the
  19690.  format result in failure. The scanf function terminates as soon as it
  19691.  reads an extended character, even if it is the same as the expected
  19692.  character in the format. For example, if the format string contains
  19693.  "??%d", and "??45" is input, scanf quits reading at "??" even though
  19694.  it matches, since it does not recognize the extended ASCII value.
  19695.  
  19696.  This problem does not occur in QuickC Versions 2.00 and 2.01.
  19697.  
  19698.  The following program demonstrates this situation. In the first case,
  19699.  scanf expects "sqrt" to be typed in followed by a number. If this is
  19700.  done correctly, then scanf reads the number and the square root is
  19701.  displayed. In the second case, scanf should be expecting the "??"
  19702.  symbol followed by a number, but if this is typed in, scanf still
  19703.  fails to read the number since it was unable to correctly match the
  19704.  "??" to the format string.
  19705.  
  19706.  /* Before running this program, replace all occurrences of "??" with
  19707.     extended ASCII character 251. (Hold down the ALT key and type 251
  19708.     on the numeric keypad, then release the ALT key.)              */
  19709.  
  19710.  #include <stdio.h>
  19711.  #include <math.h>
  19712.  
  19713.  void main(void)
  19714.  {
  19715.      int    values_read;
  19716.      double num;
  19717.  
  19718.      /* THIS PART WORKS - scanf recognizes "sqrt" in format string */
  19719.  
  19720.      printf( "Enter sqrtNUMBER by typing \"sqrt\" followed by any "
  19721.              "NUMBER >= 0\n(e.g sqrt87.6) : ");
  19722.      values_read = scanf( "sqrt%lf", &num);
  19723.      printf( "values_read = %d\n", values_read);
  19724.      printf( "sqrt%lf = %lf\n\n", num, sqrt(num));
  19725.      fflush(stdin);
  19726.  
  19727.      /* THIS PART DOES NOT WORK - scanf fails to recognize "??" in
  19728.         the format string */
  19729.  
  19730.      printf( "Enter ??NUMBER by holding down the <ALT> key while "
  19731.              "typing\n\"251\" on the numeric keypad followed by "
  19732.              "any NUMBER >= 0\n(e.g. ??87.6) : ");
  19733.      values_read = scanf( "??%lf", &num);            /* returns 0 */
  19734.      printf( "values_read = %d\n", values_read);
  19735.      printf( "??%lf = %lf\n\n", num, sqrt(num));
  19736.  }
  19737.  
  19738.  
  19739.  444. FP_SEG(), FP_OFF() Need Pointer Rather Than Address
  19740.  
  19741.  Product Version(s): 5.00 5.10 | 5.00 5.10
  19742.  Operating System:   MS-DOS    | OS/2
  19743.  Flags: ENDUSER | S_QuickC
  19744.  Last Modified: 31-AUG-1989    ArticleIdent: Q47497
  19745.  
  19746.  Because FP_SEG() and FP_OFF() macros de-reference the pointer values
  19747.  passed to them, the address of a variable cannot be passed as a
  19748.  parameter.
  19749.  
  19750.  The FP_SEG() and FP_OFF() macros are defined in DOS.H as follows:
  19751.  
  19752.     #define FP_SEG(fp) (*((unsigned *)&(fp) + 1))
  19753.     #define FP_OFF(fp) (*((unsigned *)&(fp)))
  19754.  
  19755.  The first step of the macro is to take the address of the pointer that
  19756.  is passed to it. Because of this, the code
  19757.  
  19758.     unsigned val;
  19759.     unsigned i;
  19760.     i = FP_OFF(&val);
  19761.  
  19762.  produces the following error in C 5.00 and 5.10, as well as QuickC
  19763.  1.01:
  19764.  
  19765.     C2102:  '&' requires lvalue
  19766.  
  19767.  QuickC 2.00 produces the following warning, which does not hinder
  19768.  compilation:
  19769.  
  19770.     C4046:  '&' on function/array, ignored
  19771.  
  19772.  These messages occur because the macro cannot take the address of an
  19773.  address. However, the code
  19774.  
  19775.     unsigned val, *valptr;
  19776.     unsigned i;
  19777.     valptr = &val;
  19778.     i = FP_OFF(valptr);
  19779.  
  19780.  returns the offset of the variable val, as the address of valptr can
  19781.  be taken.
  19782.  
  19783.  
  19784.  445. Determining the Number of Valid Drives in DOS
  19785.  
  19786.  Product Version(s): 5.10
  19787.  Operating System:   MS-DOS
  19788.  Flags: ENDUSER | S_QuickC S_QuickASM H_MASM O_MSDOS
  19789.  Last Modified:  9-AUG-1989    ArticleIdent: Q47484
  19790.  
  19791.  Question:
  19792.  
  19793.  I have an application that needs to determine the number of logical
  19794.  drives installed on a given computer. I have tried using the DOS
  19795.  function "SelectDisk" (0x0E), but it seems to return the number 5 on
  19796.  all machines, no matter how many drives are installed. Is there a way
  19797.  to get this information from DOS?
  19798.  
  19799.  Response:
  19800.  
  19801.  There are no DOS calls for determining the number of logical drives
  19802.  installed on a computer. The DOS call SelectDisk returns only the
  19803.  value stored in the DOS variable LASTDRIVE. This variable normally
  19804.  contains 5 (maximum drive letter is "E") unless LASTDRIVE is
  19805.  specifically set in the CONFIG.SYS file.
  19806.  
  19807.  The LASTDRIVE value is useful, however, when determining which drives
  19808.  are valid and which are not. Since LASTDRIVE reflects the highest
  19809.  available drive letter, we can use DOS calls to determine which of the
  19810.  available drives are valid. The DOS calls SelectDisk (0x0E) and
  19811.  GetDisk (0x19) can be used to provide this information.
  19812.  
  19813.  Note: Any network drives to which you're attached are also considered
  19814.  valid. If you need to distinguish between network and non-network
  19815.  drives, modify the program below to use INT 21h function 44h (IOCTL),
  19816.  subfunction 09h ("Check if block device is remote"). For more
  19817.  information, see a good DOS reference such as "Advanced MS-DOS
  19818.  Programming" (by Duncan, published by Microsoft Press), or the "MS-DOS
  19819.  Encyclopedia" (also published by Microsoft Press).
  19820.  
  19821.  If you try, one at a time, to change the current drive to each of the
  19822.  available drive letters, you will see which ones are valid. Since
  19823.  SelectDisk does not return an error code in the event that it fails to
  19824.  select a new disk, call GetDisk afterwards to determine if it was
  19825.  successful.
  19826.  
  19827.  The following C source code illustrates this method:
  19828.  
  19829.  /*
  19830.  
  19831.  Will not run under OS/2.  For DOS only.
  19832.  
  19833.  The following program displays all of the logical drives installed on
  19834.  a DOS system. This program uses DOS function calls to obtain the
  19835.  current drive and change it to a new drive.
  19836.  
  19837.  */
  19838.  
  19839.  #include <stdio.h>
  19840.  #include <dos.h>
  19841.  
  19842.  /* simple types */
  19843.  
  19844.  #define BYTE unsigned char
  19845.  #define BOOLEAN int
  19846.  
  19847.  /* function prototypes */
  19848.  
  19849.  BYTE DosGetDisk(void);
  19850.  int DosSelectDisk(BYTE);
  19851.  BOOLEAN ValidDrive(BYTE);
  19852.  
  19853.  void main(void)
  19854.  {
  19855.  BYTE CurDrive;
  19856.  int  NumDrives;
  19857.  int  x;
  19858.  
  19859.  CurDrive  = DosGetDisk();                // currently active drive
  19860.  NumDrives = DosSelectDisk(CurDrive);     // returns number set in
  19861.                                           // LASTDRIVE
  19862.  
  19863.  for (x = 0; x < NumDrives; x++)   // go through all possible drives
  19864.    if (ValidDrive((BYTE)x))        // print message if drive x valid
  19865.      printf("Drive %c is valid\n",(char)x+'A');
  19866.  
  19867.  DosSelectDisk(CurDrive);          // set default drive back
  19868.  
  19869.  }  /* end of main */
  19870.  
  19871.  BOOLEAN ValidDrive(BYTE drive)  // returns true if drive valid,
  19872.  {                               // false otherwise
  19873.    DosSelectDisk(drive);         // attempt to make drive current
  19874.  
  19875.    return (DosGetDisk() == drive);  // did it succeed?
  19876.  }
  19877.  
  19878.  BYTE DosGetDisk(void)   // returns drive number of current drive
  19879.  {
  19880.    union REGS reg;
  19881.  
  19882.    reg.h.ah = 0x19;           // call DOS to find
  19883.    int86(0x21,®,®);
  19884.  
  19885.    return (reg.h.al);
  19886.  }
  19887.  
  19888.  int DosSelectDisk(BYTE drive)      // sets current drive
  19889.  {
  19890.    union REGS reg;
  19891.  
  19892.    reg.h.ah = 0x0e;                 // set by calling DOS
  19893.    reg.h.dl = drive;
  19894.    int86(0x21,®,®);
  19895.  
  19896.    return ((int) reg.h.al);
  19897.  }
  19898.  
  19899.  
  19900.  446. Variable Width, Precision Available with printf
  19901.  
  19902.  Product Version(s): 5.00 5.10 | 5.00 5.10
  19903.  Operating System:   MS-DOS    | OS/2
  19904.  Flags: ENDUSER | S_QuickC 1.00 1.10 2.00 2.01 S_QuickASM
  19905.  Last Modified:  9-AUG-1989    ArticleIdent: Q47663
  19906.  
  19907.  The Microsoft run-time library function printf() allows the width of
  19908.  the format specifier to be supplied at run time. This is done with the
  19909.  use of the * with the format specifier. This is mentioned on Pages 460
  19910.  and 461 of the "Microsoft C 5.1 Optimizing Compiler Run-Time Library
  19911.  Reference." The following code sample demonstrates this capability.
  19912.  
  19913.  Code Sample
  19914.  -----------
  19915.  
  19916.  /* This program defines a procedure to print out a floating point
  19917.     number with variable width and precision.
  19918.  */
  19919.  #include <stdio.h>
  19920.  
  19921.  void print(int, int, float);
  19922.  
  19923.  void main(void) {
  19924.     print (10, 2, 1234.5678f);
  19925.     print (9, 4, 1234.5678f);
  19926.     print (5, 2, 1234.5678f);
  19927.  }
  19928.  
  19929.  void print(int w, int p, float value)  {
  19930.     printf ("Printf format :%*.*f\n", w, p, value);
  19931.     printf ("Width =        0123456789012\n");
  19932.  }
  19933.  
  19934.  
  19935.  447. errno Values Not Used under MS-DOS Indicate Other Problem
  19936.  
  19937.  Product Version(s): 5.00 5.10
  19938.  Operating System:   MS-DOS
  19939.  Flags: ENDUSER | S_QuickC
  19940.  Last Modified:  9-AUG-1989    ArticleIdent: Q47692
  19941.  
  19942.  When an error occurs in some library routines, the errno variable is
  19943.  set to a value that can be used to indicate the nature of the error.
  19944.  These error codes are defined in the file errno.h. The codes
  19945.  originally were set up for use with UNIX to conform to errors
  19946.  occurring under that operating system. Because of this, and the
  19947.  differences between MS-DOS and UNIX, many of the codes have no
  19948.  relevance to the MS-DOS environment.
  19949.  
  19950.  In order to maintain compatibility with UNIX and XENIX, all the codes,
  19951.  whether meaningful in MS-DOS or not, are defined in errno.h. Appendix
  19952.  A of the "Microsoft C 5.1 Optimizing Compiler Run-Time Library
  19953.  Reference" lists only those codes that have meaning under MS-DOS along
  19954.  with their description and causes. These specific codes have
  19955.  corresponding error messages that can be printed out with the perror
  19956.  function.
  19957.  
  19958.  If you are working under MS-DOS and you obtain an errno value that is
  19959.  not one of the listed codes, then you can assume that the code was
  19960.  generated incorrectly and it is not indicative of the true problem.
  19961.  The documentation for the specific function you are using says which
  19962.  errno values, if any, may be set by an error in that function.
  19963.  
  19964.  The following is a listing of all the errno values defined in errno.h
  19965.  along with brief descriptions of their meanings. Only the values that
  19966.  are marked with "*" may be considered valid under DOS. For more
  19967.  information on these, see Appendix A of the "Microsoft C 5.1
  19968.  Optimizing Compiler Run-Time Library Reference." For more information
  19969.  on the others that are not marked with an asterisk (*), see a UNIX or
  19970.  XENIX system manual.
  19971.  
  19972.  * Used under MS-DOS
  19973.  
  19974.  Value     Define      Description
  19975.  -----     ------      -----------
  19976.  
  19977.  EPERM         1       Not owner
  19978.  ENOENT        2      *No such file or directory
  19979.  ESRCH         3       No such process
  19980.  EINTR         4       Interrupted system call
  19981.  EIO           5       I/O error
  19982.  ENXIO         6       No such device or address
  19983.  E2BIG         7      *Arg list too long
  19984.  ENOEXEC       8      *Exec format error
  19985.  EBADF         9      *Bad file number
  19986.  ECHILD       10       No child processes
  19987.  EAGAIN       11       No more processes
  19988.  ENOMEM       12      *Not enough space
  19989.  EACCES       13      *Permission denied
  19990.  EFAULT       14       Bad address
  19991.  ENOTBLK      15       Block device required
  19992.  EBUSY        16       Mount device busy
  19993.  EEXIST       17      *File exists
  19994.  EXDEV        18      *Cross-device link
  19995.  ENODEV       19       No such device
  19996.  ENOTDIR      20       Not a directory
  19997.  EISDIR       21       Is a directory
  19998.  EINVAL       22      *Invalid argument
  19999.  ENFILE       23       File table overflow
  20000.  EMFILE       24      *Too many open files
  20001.  ENOTTY       25       Not a teletype
  20002.  ETXTBSY      26       Text file busy
  20003.  EFBIG        27       File too large
  20004.  ENOSPC       28      *No space left on device
  20005.  ESPIPE       29       Illegal seek
  20006.  EROFS        30       Read-only file system
  20007.  EMLINK       31       Too many links
  20008.  EPIPE        32       Broken pipe
  20009.  EDOM         33      *Math argument
  20010.  ERANGE       34      *Result too large
  20011.  EUCLEAN      35       File system needs cleaning
  20012.  EDEADLOCK    36      *Would deadlock
  20013.  
  20014.  
  20015.  448. Initializing Unions Initializes the First Member of the Union
  20016.  
  20017.  Product Version(s): 5.10   | 5.10
  20018.  Operating System:   MS-DOS | OS/2
  20019.  Flags: ENDUSER | S_QuickC S_QuickASM
  20020.  Last Modified: 16-AUG-1989    ArticleIdent: Q47693
  20021.  
  20022.  When you initialize a union, the initialization value is applied to
  20023.  the first member of the union even if the type of the value matches a
  20024.  subsequent member. As stated in the ANSI Standard, Section 3.5.7:
  20025.  
  20026.     A brace-enclosed initializer for a union object initializes the
  20027.     member that appears first in the declaration list of the union
  20028.     type.
  20029.  
  20030.  Since you cannot initialize the value of any member of a union other
  20031.  than the first one, you must assign their values in a separate
  20032.  statement. Initializing a union with a value intended for a subsequent
  20033.  member causes that value to be converted to the type of the first
  20034.  member.
  20035.  
  20036.  The following example demonstrates the issue:
  20037.  
  20038.  #include <stdio.h>
  20039.  union { int   a;         /* only external unions may be initialized */
  20040.          float b;
  20041.        } test = {3.6};    /* this is intended to initialize 'b'      */
  20042.                           /* however, the value will be converted    */
  20043.                           /* (first to a long and then to an int)    */
  20044.                           /* in order to initialize 'a'              */
  20045.  
  20046.  void main (void)
  20047.  {
  20048.     float dummy = 0.0;            /* this causes the floating point  */
  20049.                                   /* math package to be initialized  */
  20050.  
  20051.     printf ("test.a = %d,  test.b = %f\n", test.a, test.b);
  20052.  }
  20053.  
  20054.  The output from the example, though not what is intended, will be as
  20055.  follows:
  20056.  
  20057.  test.a = 3, test.b = 0.00000
  20058.  
  20059.  To associate a value with "b", you can reverse the order of the
  20060.  members, as in the following:
  20061.  
  20062.  union {
  20063.          float b;
  20064.          int a;
  20065.        } test = {3.6};
  20066.  
  20067.  Or, you can retain the order of the elements and assign the value in a
  20068.  separate statement, as in the following:
  20069.  
  20070.  test.b = 3.6;
  20071.  
  20072.  Either of these methods creates the following output:
  20073.  
  20074.  test.a = 26214, test.b = 3.600000
  20075.  
  20076.  
  20077.  449. Network License Agreement for All Microsoft Language Products
  20078.  
  20079.  Product Version(s): 5.10   | 5.10
  20080.  Operating System:   MS-DOS | OS/2
  20081.  Flags: ENDUSER | S_QuickC S_QuickASM S_PasCal S_QuickPas
  20082.  Last Modified:  4-JAN-1990    ArticleIdent: Q47724
  20083.  
  20084.  Network license agreements do not exist for any of the Microsoft
  20085.  language products. These agreements are currently available only for
  20086.  our application products.
  20087.  
  20088.  According to the licensing agreement printed on the envelope that
  20089.  contains the disks, our languages are licensed as single-user,
  20090.  single-workstation products and cannot be used by more than one user
  20091.  simultaneously. Running off of a network server or installing copies
  20092.  on more than one workstation is specifically prohibited by this
  20093.  agreement. However, the agreement does allow users to share the
  20094.  software if they run it off the same workstation at different times.
  20095.  
  20096.  In a networked environment, each node on the network that will be used
  20097.  for development must have a copy of the product installed on a local
  20098.  drive. Work files can be shared over the network, but neither
  20099.  compilers nor the associated utilities of a package can be shared over
  20100.  the network.
  20101.  
  20102.  
  20103.  450. Filelength() Includes EOF Character in Return Value
  20104.  
  20105.  Product Version(s): 5.00 5.10 | 5.10
  20106.  Operating System:   MS-DOS    | OS/2
  20107.  Flags: ENDUSER | S_QuickC 2.00
  20108.  Last Modified: 14-AUG-1989    ArticleIdent: Q47737
  20109.  
  20110.  The return value of the filelength function is the full length of the
  20111.  file in bytes, including any EOF characters. The return value returns
  20112.  the same file size value as the DIR command from the DOS or OS/2
  20113.  prompt.
  20114.  
  20115.  
  20116.  451. Closing stdprn and stdaux May Not Increase Available Handles
  20117.  
  20118.  Product Version(s): 5.10
  20119.  Operating System:   MS-DOS
  20120.  Flags: ENDUSER | SR# G890728-23559
  20121.  Last Modified: 16-AUG-1989    ArticleIdent: Q47741
  20122.  
  20123.  Question:
  20124.  
  20125.  We are trying to close the handles for stdaux and stdprn so that we
  20126.  can open additional files before hitting the limit of the FILES=
  20127.  parameter in CONFIG.SYS (which we set to 11). In that mode, regardless
  20128.  of whether or not we close handles 3 and 4 (stdaux and stdprn), we are
  20129.  able to open only 8 files (FILES= - 3). The "MS-DOS Encyclopedia"
  20130.  states that stdin, out, and err are mapped to one device, but use
  20131.  three handles.
  20132.  
  20133.  We noticed that if FILES= in CONFIG.SYS is set to 20 or above, the
  20134.  program DOES get additional files opened when handles 3 and 4 are
  20135.  closed. Apparently we're getting some sort of interaction between the
  20136.  process file-handle table/limit (of 20) and the system table/setting
  20137.  from CONFIG.SYS.
  20138.  
  20139.  How can we gain access to those two file handles, keeping our FILES=
  20140.  setting in CONFIG.SYS at 11? We want to be able to open 10 files in
  20141.  our program, with FILES= set to 11.
  20142.  
  20143.  Response:
  20144.  
  20145.  Due to a limitation of DOS, you can't do this. The workaround is to
  20146.  simply set FILES=13, for the reasons described below.
  20147.  
  20148.  In order to open a file using the C run time, ALL of the following
  20149.  conditions must be true:
  20150.  
  20151.  1. There must be a space in the C run-time library's internal file
  20152.     tables. This is normally limited to 20 files, but this limit can be
  20153.     increased by modifying the start-up code if you're using DOS 3.30
  20154.     or later.
  20155.  
  20156.  2. There must be DOS file handles available to your particular
  20157.     process. Again, the normal limit is 20, but this can be increased
  20158.     with a call to function 67h of INT 21h (only under DOS 3.30 or
  20159.     later). This can also be modified in the start-up code.
  20160.  
  20161.  3. Finally, there must be files available from DOS's system-wide pool,
  20162.     as set by FILES= in CONFIG.SYS. (This defaults to 8, but can be set
  20163.     as high as 20 under DOS Version 3.30 and earlier or 255 under
  20164.     Versions 3.30 and later.)
  20165.  
  20166.  The results of comparing a C program that uses the C run-time library
  20167.  and a MASM program that calls DOS directly are shown below. Each was
  20168.  run with stdprn and stdaux, closed and open.
  20169.  
  20170.                              C Program               MASM Program
  20171.                              ---------               ------------
  20172.  
  20173.     FILES=         W/o Closing    W/ Closing  W/o Closing   W/ Closing
  20174.     ------         -----------    ----------  -----------   ----------
  20175.  
  20176.     17 (Note 1)        14             14          14            14
  20177.     18 (Note 1)        15             15          15            15
  20178.     19                 15             16          16            16
  20179.     20                 15             17          17            17
  20180.     21 (Note 2)        15             17          17            17
  20181.  
  20182.  Please note the following:
  20183.  
  20184.  1. The formula for the number of files you can open for FILES=n, where
  20185.     n is less than 19, is n - 3.
  20186.  
  20187.  2. No matter how high you set FILES=, you'll be limited to these
  20188.     numbers in C unless you modify the start-up code as described in
  20189.     README.DOC. In MASM, you'll be limited to these numbers unless you
  20190.     raise the per-process limit on file handles by calling INT 21h,
  20191.     function 67h.
  20192.  
  20193.  3. Running the program from a batch file doesn't change these numbers;
  20194.     however, reduce each number by 1 for each input or output
  20195.     redirection you do.
  20196.  
  20197.  4. The MASM program doesn't get any additional handles freed up when
  20198.     it closes handles 3 and 4 because, contrary to what the "MS-DOS
  20199.     Encyclopedia" implies, DOS won't allow you to reuse those two
  20200.     handles.
  20201.  
  20202.  Without closing handles, C programs give you a constant 15 or n - 3,
  20203.  whichever is smaller. The upper limit is 15 because, unless you modify
  20204.  the start-up code, the limit is 20 minus the five default files.
  20205.  
  20206.  When you close handles 3 and 4, they are closed for C but not for DOS.
  20207.  Therefore, you can open exactly as many handles as DOS normally
  20208.  allows.
  20209.  
  20210.  
  20211.  452. _amblksiz Affects Memory Allocation in Near and Far Heaps
  20212.  
  20213.  Product Version(s): 5.10   | 5.10
  20214.  Operating System:   MS-DOS | OS/2
  20215.  Flags: ENDUSER | docerr
  20216.  Last Modified: 16-AUG-1989    ArticleIdent: Q47766
  20217.  
  20218.  The documentation on Page 33 of the "Microsoft C for the MS-DOS
  20219.  Operating System: Run-Time Library Reference" states that adjusting
  20220.  the value of the global variable _amblksiz has no effect on halloc or
  20221.  _nmalloc() in any memory model.
  20222.  
  20223.  This statement in the manual is incorrect. In fact, _amblksiz is used
  20224.  to determine how much to expand both the near heap and the far heap
  20225.  segments, and is used by calls to _nmalloc(). The only difference
  20226.  between calls to _nmalloc() and _fmalloc is that _nmalloc() doesn't
  20227.  actually request memory from DOS, it takes it from the pre-allocated
  20228.  heap (in DOS).
  20229.  
  20230.  However, since the the memory allocated by a call to halloc() is
  20231.  maintained independently of the near and far heaps, the value of
  20232.  _amblksiz does not affect calls to halloc().
  20233.  
  20234.  The default value of _amblksiz is 8K (8192) bytes. The variable is
  20235.  declared in malloc.h. For more information about the use of _amblksiz,
  20236.  refer to the "Microsoft C for the MS-DOS Operating System: Run-Time
  20237.  Library Reference," Section 3.2.
  20238.  
  20239.  
  20240.  453. Linking without /NOI Causes SYS2070 in Program Calling CRTLIB
  20241.  
  20242.  Product Version(s): 5.10
  20243.  Operating System:   OS/2
  20244.  Flags: ENDUSER | SR# G890807-24188
  20245.  Last Modified: 16-JAN-1990    ArticleIdent: Q47779
  20246.  
  20247.  Programs that are linked with the C run-time library DLL (CRTDLL),
  20248.  without the /NOI switch, fail with the following message:
  20249.  
  20250.     SYS2070:  The system could not demand load the application's
  20251.     segment.  CRTLIB __STDOUT is in error.
  20252.  
  20253.  To avoid the problem, use the /NOI switch when linking. The proper use
  20254.  of /NOI is described in Section 5.2 of the MTDYNA.DOC file supplied
  20255.  with Microsoft C Version 5.10.
  20256.  
  20257.  
  20258.  454. Blinking Text May Be Eliminated with BIOS Call
  20259.  
  20260.  Product Version(s): 5.00 5.10
  20261.  Operating System:   MS-DOS
  20262.  Flags: ENDUSER | S_QuickC S_QuickASM EGA
  20263.  Last Modified: 16-JAN-1990    ArticleIdent: Q47780
  20264.  
  20265.  Blinking text can be accessed by setting the foreground text color to
  20266.  a value of 16 or greater. However, this can be affected by a BIOS call.
  20267.  BIOS call 10, subfunction 3 toggles the interpretation of the
  20268.  intensity bit of the foreground color. By making a call to this BIOS
  20269.  function you can access additional background colors. Without blinking
  20270.  foreground text, you can access 16 background colors. With blinking
  20271.  text you are limited to 8 background colors. The program shown below
  20272.  demonstrates this.
  20273.  
  20274.  The example prints 16 lines of text with varying background colors.
  20275.  The intensity interpretation is then toggled, limiting the output to
  20276.  only 8 background colors.
  20277.  
  20278.  This problem also occurs in Microsoft QuickC Versions 1.00, 1.01,
  20279.  2.00, and 2.01.
  20280.  
  20281.  Sample Program:
  20282.  --------------
  20283.  
  20284.  #include <stdio.h>
  20285.  #include <graph.h>
  20286.  #include <dos.h>
  20287.  #include <conio.h>
  20288.  
  20289.  #define TRUE 1
  20290.  #define FALSE 0
  20291.  
  20292.  void toggle_intensity(int);
  20293.  
  20294.  void main(void)  {
  20295.     long i;
  20296.     char buf[80];
  20297.     _clearscreen(_GCLEARSCREEN);
  20298.     toggle_intensity(0);
  20299.     for (i=16; i < 32; i++) {
  20300.        _setbkcolor (i);
  20301.        _settextcolor (i+1);
  20302.        _settextposition (i-15, 10);
  20303.        sprintf(buf, "  Background = %2ld  Foreground = %2d  \n",i,i+1);
  20304.        _outtext (buf);
  20305.     }
  20306.     getch();
  20307.  
  20308.     _setbkcolor (_BLACK);
  20309.     _clearscreen(_GCLEARSCREEN);
  20310.     toggle_intensity(1);
  20311.     for (i=16; i < 32; i++) {
  20312.        _setbkcolor (i);
  20313.        _settextcolor (i+1);
  20314.        _settextposition (i-15, 10);
  20315.        sprintf (buf, "  Background = %2ld  Foreground = %2d  \n", i, i+1);
  20316.        _outtext (buf);
  20317.     }
  20318.     getch();
  20319.  }
  20320.  
  20321.  /*  If onoff is True, intesity bit will indicate blinking text  */
  20322.  void toggle_intensity(int onoff)  {
  20323.      #define         VIDEO_IO        0x10
  20324.      #define         BIOS_CALL       0x10
  20325.      #define         INTENSITY_TGL   0x03
  20326.      union REGS regs;
  20327.  
  20328.      regs.h.ah = VIDEO_IO;
  20329.      regs.h.al = INTENSITY_TGL;
  20330.      if (!onoff)
  20331.         regs.h.bl = 0x0;
  20332.      else
  20333.         regs.h.bl = 0x1;
  20334.      int86 (BIOS_CALL, ®s, ®s);
  20335.  }
  20336.  
  20337.  
  20338.  455. Effective Limit of 52 Threads Per Process with DosCreateThread
  20339.  
  20340.  Product Version(s): 5.10
  20341.  Operating System:   OS/2
  20342.  Flags: ENDUSER | docerr OpSys PMWin
  20343.  Last Modified: 16-JAN-1990    ArticleIdent: Q47933
  20344.  
  20345.  A single process running under OS/2 Version 1.10 or 1.00 is limited to
  20346.  creating 52 threads with DosCreateThread.
  20347.  
  20348.  Attempting to create additional threads results in a return value
  20349.  from DosCreateThread of 155, which is defined as ERROR_TOO_MANY_TCBS
  20350.  (Thread Control BlockS) in BSEERR.H.
  20351.  
  20352.  The "Microsoft OS/2 Programmer's Reference," Volume 3, Page 34,
  20353.  incorrectly states "DosCreateThread can create up to 255 threads per
  20354.  process." The Reference also fails to note that DosCreateThread could
  20355.  return ERROR_TOO_MANY_TCBS.
  20356.  
  20357.  The only way to work around the current OS/2 1.x limitation with
  20358.  DosCreateThread is by starting additional processes, with each process
  20359.  being limited to 52 threads. OS/2 1.10 and 1.00 can support up to 255
  20360.  threads total for all processes in the entire system.
  20361.  
  20362.  An increase in the limit will be considered for inclusion in a future
  20363.  release.
  20364.  
  20365.  Note that threads that will be calling C run-time library functions
  20366.  should be created with _beginthread, which performs essential library
  20367.  initializations that DosCreateThread does not perform. The library
  20368.  function _beginthread is limited to creating 31 threads in C 5.10, for
  20369.  a total of 32 threads. The next version of C will support the creation
  20370.  of substantially more threads with its _beginthread.
  20371.  
  20372.  
  20373.  456. Patching malloc() to Reuse Memory within an Allocated Block
  20374.  
  20375.  Product Version(s): 5.00 5.10
  20376.  Operating System:   MS-DOS
  20377.  Flags: ENDUSER |
  20378.  Last Modified: 16-JAN-1990    ArticleIdent: Q47958
  20379.  
  20380.  The malloc() family of functions properly reuse the blocks of memory
  20381.  that they allocate from DOS. The size of a block that malloc()
  20382.  allocates is 8K bytes by default, but can be modified by assigning a
  20383.  different block size in bytes to the C run-time library variable
  20384.  "_amblksiz", as noted on Page 33 of the "Microsoft C 5.1 Optimizing
  20385.  Compiler Run-Time Library Reference."
  20386.  
  20387.  However, for small suballocations of "chunks" (author's terminology)
  20388.  within an 8K block, previously freed chunks will not be immediately
  20389.  reused and fragmentation within blocks can occur; this can cause DOS
  20390.  programs that make many small (e.g. 10-byte) allocations to
  20391.  prematurely run out of memory. This problem occurs because the "rover"
  20392.  pointer that points to the next chunk of memory to be allocated points
  20393.  to the memory after the last chunk allocated without being set to
  20394.  point to the beginning of chunks that were freed.
  20395.  
  20396.  Reducing the size of allocated blocks by declaring _amblksiz as above
  20397.  and assigning values under 8096 to it may help reduce fragmentation
  20398.  within blocks in some cases simply because there is less memory to
  20399.  lose to fragmentation per block and your allocations and frees are
  20400.  more likely to be on reusable block boundaries.
  20401.  
  20402.  A better alternative would be to allocate large blocks yourself, then
  20403.  perform your own memory management within them to prevent
  20404.  fragmentation within blocks.
  20405.  
  20406.  For those who purchase the C run-time library source code for C 5.10
  20407.  available through our Sales department at (800) 426-9400, you can
  20408.  force the rover pointer to point at the bottom of the block prior to a
  20409.  memory request as noted below, so that any adequately large freed
  20410.  chunks will be reused. This technique will result in executable speed
  20411.  degradation, but will more fully allocate the last bytes of memory.
  20412.  
  20413.  To change the behavior of the rover pointer to reallocate freed chunks
  20414.  of memory within a block, make the following change to line 83 of
  20415.  AMALLOC.ASM, the workhorse module called by malloc() functions:
  20416.  
  20417.  1. Delete or comment out line 83 with a semicolon (;), as follows:
  20418.  
  20419.      ;   mov     si,[bx].roveroff; si = starting rover offset
  20420.  
  20421.  2. Replace the line above with the following two lines:
  20422.  
  20423.          mov     si,[bx].bottom
  20424.          mov     [bx].roveroff,si ;*** put rover at bottom each time
  20425.  
  20426.  3. Reassemble AMALLOC.ASM with MASM, as follows
  20427.  
  20428.          masm /Mx /Dmem_L amalloc;
  20429.  
  20430.     where the /Mx option preserves symbol name case sensitivity, and
  20431.     /Dmem_L defines the constant to indicate large memory model for
  20432.     pointers defined by macros in AMALLOC.ASM and other .ASM files used
  20433.     for the C library. The constant "mem_L" is for large model, "mem_S"
  20434.     for small, "mem_C" for compact, and "mem_M" is for medium model.
  20435.  
  20436.  4. Either link with the new AMALLOC.OBJ (and /NOE), or use lib to
  20437.     replace the module in the appropriate memory model library, as
  20438.     follows:
  20439.  
  20440.          lib llibcer.lib -+amalloc;
  20441.  
  20442.  
  20443.  457. Description of a .MAP File's "Program Entry Point"
  20444.  
  20445.  Product Version(s): 5.00 5.10 | 5.10
  20446.  Operating System:   MS-DOS    | OS/2
  20447.  Flags: ENDUSER |
  20448.  Last Modified: 16-JAN-1990    ArticleIdent: Q47959
  20449.  
  20450.  The "Program entry point" is the last item in a .MAP file. It refers
  20451.  to the segment:offset address of the first instruction of the program
  20452.  to be executed, relative to the lowest memory address in the .EXE load
  20453.  image (the program loaded into RAM). A more detailed description and
  20454.  the use of entry point(s) are noted below.
  20455.  
  20456.  The load address can be obtained by adding 10h to the segment address
  20457.  of the PSP. (In C, this is available in the variable _psp.)
  20458.  
  20459.  An entry point is where code in a module actually begins execution
  20460.  via the loading of the CS:IP (CodeSegment:InstructionPointer --
  20461.  segment:offset) registers with the entry point address. The entry
  20462.  point could be the actual beginning of a program executed by the
  20463.  operating system, or it could be an exported function from an
  20464.  OS/2 or DOS Windows dynamic link library (DLL).
  20465.  
  20466.  The "Program entry point" specified at the end of a .MAP file is where
  20467.  the operating system will begin executing the program, RELATIVE to the
  20468.  lowest memory address where the program's code will be loaded. In DOS
  20469.  or real-mode OS/2, the lowest memory address will be the lowest
  20470.  physical address in RAM. In protected-mode OS/2, the lowest relative
  20471.  address will be segment selector 1, offset 0.
  20472.  
  20473.  The lowest address your code occupies in RAM is usually the first
  20474.  routine (function, procedure, or main program body) defined at the
  20475.  beginning of your main source file, and it is assigned a RELATIVE
  20476.  address of 0000:0000 [or, typically, 0:10 for main()] in DOS or
  20477.  real-mode OS/2, or an address of 0001:0000 in protected-mode OS/2.
  20478.  
  20479.  For our current high-level languages (except Microsoft QuickPascal
  20480.  1.00), the entry point is at the beginning of the routine "__astart".
  20481.  Our high-level languages require initialization code before executing
  20482.  C's main() function or the main program code for other languages such
  20483.  as Microsoft Pascal 3.3x or 4.00, and currently __astart is where the
  20484.  initializations begin.
  20485.  
  20486.  The "Program entry point" is a segment:offset address above the
  20487.  program's relative address of 0:0. For a C program, the entry point
  20488.  will be __astart. If the entry point is something like 2:0abc hex, the
  20489.  absolute DOS physical address or the virtual OS/2 address where
  20490.  __astart will be located can be calculated as follows:
  20491.  
  20492.       lowest address of your program's load image  1234:0400
  20493.     + relative entry point                         +  2:0abc
  20494.     ---------------------------------------------  ---------
  20495.     = DOS absolute or OS/2 virtual address of      1236:0e34
  20496.       the entry point (__astart)
  20497.  
  20498.  
  20499.  458. Extracting a Function ptr from a Variable arg List Function
  20500.  
  20501.  Product Version(s): 5.10   | 5.10
  20502.  Operating System:   MS-DOS | OS/2
  20503.  Flags: ENDUSER | S_quickC S_QuickASM
  20504.  Last Modified: 16-JAN-1990    ArticleIdent: Q47961
  20505.  
  20506.  To remove an item from a variable argument list, you use the va_arg()
  20507.  macro. However, when the element to be removed is complex, you may
  20508.  have to typedef the item type. This is necessary because the va_arg()
  20509.  macro requires you to provide the type of the item to be removed from
  20510.  the list. For a pointer to a function, if you were to put the item
  20511.  type (the declaration of the function ptr) as follows
  20512.  
  20513.        FuncPtr = va_arg (arg_list, (int(*)(void)) );
  20514.  
  20515.  the compiler would yield the following error:
  20516.  
  20517.        C2059: Syntax Error : ')'
  20518.  
  20519.  You could attempt to get around this by grabbing the function pointer
  20520.  as a data pointer, and then typecasting it to a function pointer, as
  20521.  in the following line:
  20522.  
  20523.        FuncPtr = (int (*)(void)) va_arg (arg_list, char *);
  20524.  
  20525.  This would work; however, you will get the following warning:
  20526.  
  20527.        C4074: Non-standard extension used, cast of data pointer
  20528.               to function pointer
  20529.  
  20530.  The best solution to this dilemma is to typedef the function pointer.
  20531.  With a typedef, you avoid both the error and the warning.
  20532.  
  20533.  This problem occurs in C Version 5.10 and in QuickC Version 2.00 and
  20534.  2.01.
  20535.  
  20536.  The following example passes a function pointer to a variable argument
  20537.  list function, changes that pointer, and returns it to the calling
  20538.  procedure. To implement this, however, you need to pass the function
  20539.  pointer by reference. For this reason, a pointer is typedef'd to a
  20540.  function pointer. Once in the variable argument list function, the
  20541.  pointer is dereferenced to the function pointer to get at the actual
  20542.  function pointer.
  20543.  
  20544.  #include <stdio.h>
  20545.  #include <stdarg.h>
  20546.  
  20547.  typedef void (*FuncPtr)(void);
  20548.  typedef FuncPtr *PFuncPtr;
  20549.  
  20550.  void hello(void);
  20551.  void varfunc(int, ...);
  20552.  
  20553.  FuncPtr func1, func2;
  20554.  int i;
  20555.  
  20556.  void main(void)  {
  20557.     func1 = hello;
  20558.     printf ("Function pointer: func1 now points to Hello()\n");
  20559.     printf ("About to use func1 to make a call to Hello()\n\n");
  20560.     func1();
  20561.     printf ("Now lets pass these function pointers to our variable");
  20562.     printf (" argument list\n");
  20563.     varfunc(2, &func1, &func2);   /* To alter ptr, pass by reference */
  20564.     printf ("\nAfter the call to the variable argument procedure,\n");
  20565.     printf ("function pointer: func2 now points to Hello()\n");
  20566.     printf ("About to use func2 to make a call to Hello()\n\n");
  20567.     func2();
  20568.  }
  20569.  
  20570.  void hello(void)  {
  20571.     printf ("Hello, I'm in the procedure HELLO()\n");
  20572.  }
  20573.  
  20574.  void varfunc(int i, ...)  {
  20575.     va_list arg_ptr;
  20576.     PFuncPtr tmpfptr;                /* Temporary ptr to function ptr */
  20577.  
  20578.     printf ("\nIn function VARFUNC\n");
  20579.     va_start (arg_ptr, i);
  20580.     printf ("%d arguments were passed\n", i);
  20581.     tmpfptr = va_arg (arg_ptr, PFuncPtr);  /* Grab pointer to fnptr */
  20582.     *tmpfptr = hello;                      /* Assign fnptr addr of fn */
  20583.     tmpfptr = va_arg (arg_ptr, PFuncPtr);  /* Grab pointer to fnptr */
  20584.     *tmpfptr = hello;                      /* Assign fnptr addr of fn */
  20585.  }
  20586.  
  20587.  
  20588.  459. Calling Order Undefined -- Function Calls in Single Expression
  20589.  
  20590.  Product Version(s): 5.00 5.10 | 5.00 5.10
  20591.  Operating System:   MS-DOS    | OS/2
  20592.  Flags: ENDUSER | S_QuickC S_QuickASM
  20593.  Last Modified: 15-JAN-1990    ArticleIdent: Q47985
  20594.  
  20595.  When C evaluates more than one function call in a single expression,
  20596.  the calls usually are made in reversed or arbitrary order, rather than
  20597.  in the stated order. Since there is no defined precedence in C for the
  20598.  order in which multiple function calls are made within a single
  20599.  expression, the result is compiler-dependent. In Microsoft's products,
  20600.  these functions are usually evaluated from right to left.
  20601.  
  20602.  This occurs in C Versions 5.00 and 5.10 and in QuickC Versions 1.01,
  20603.  2.00, and 2.01.
  20604.  
  20605.  The following code demonstrates this:
  20606.  
  20607.  void main( void )
  20608.  {
  20609.     printf( "First: %d Second: %d", getch(), getch() );
  20610.  }
  20611.  
  20612.  When this code is compiled and run, it returns first the second
  20613.  keyboard code that is scanned. For example, if the F5 key is pressed,
  20614.  returning first a null character followed by its extended code, the
  20615.  program returns "First: 63 Second: 0." The null character that is
  20616.  generated by the keyboard first, is written second.
  20617.  
  20618.  
  20619.  460. _bios_serialcom Sends and Receives Single Character Data
  20620.  
  20621.  Product Version(s): 5.00 5.10
  20622.  Operating System:   MS-DOS
  20623.  Flags: ENDUSER | docerr S_QuickC S_QuickASM
  20624.  Last Modified:  7-DEC-1989    ArticleIdent: Q47987
  20625.  
  20626.  Question:
  20627.  
  20628.  In the "Microsoft C for the MS-DOS Operating System: Run-Time Library
  20629.  Reference" manual, _bios_serialcom() is documented as taking an
  20630.  unsigned integer as the data byte. Since this is 16 bits (large enough
  20631.  for two characters), can I pass two characters (or receive two
  20632.  characters) with each call to _bios_serialcom()?
  20633.  
  20634.  Response:
  20635.  
  20636.  No, _bios_serialcom() sends (and receives) character data. Two
  20637.  characters cannot be sent (or received) with one call because the
  20638.  function call is a simple interface to the BIOS interrupt 0x14. This
  20639.  interrupt expects the data to be sent (or received) to be in the AL
  20640.  register (an 8-bit register). Therefore, the data is limited to 8
  20641.  bits, even though the function requires an unsigned integer as the
  20642.  data parameter.
  20643.  
  20644.  The parameter is an unsigned integer because the _bios_serialcom()
  20645.  function also uses the data parameter in initialization and status
  20646.  checks. In the send (and read) functions of the interrupt, however,
  20647.  only a single byte in the low-order 8 bits of the unsigned integer
  20648.  passed as the data parameter are sent. For more information, see
  20649.  interrupt 0x14 in "IBM ROM BIOS" by Ray Duncan. This book clarifies the
  20650.  interrupt calls that are being made, and what is actually passed to
  20651.  the machine.
  20652.  
  20653.  This lack of clarification for _bios_serialcom() occurs in the
  20654.  documentation for C Versions 5.00 and 5.10; in Microsoft QuickC
  20655.  Versions 1.00, 1.01, 2.00, and 2.01; and the QuickC with
  20656.  QuickAssembler on-line help Version 2.10.
  20657.  
  20658.  
  20659.  461. Possible Causes of "'__iob' : Unresolved External"
  20660.  
  20661.  Product Version(s): 5.10
  20662.  Operating System:   OS/2
  20663.  Flags: ENDUSER | SR# G890807-24188 _iob iob
  20664.  Last Modified: 16-JAN-1990    ArticleIdent: Q47990
  20665.  
  20666.  When linking with CRTLIB.LIB, the problems listed below can cause the
  20667.  following message when linking a main program to the C run-time DLL
  20668.  created as described in the MTDYNA.DOC file supplied with the C
  20669.  Compiler Version 5.10:
  20670.  
  20671.     ....  error : L2029 : '__iob' : unresolved external
  20672.  
  20673.  The problems that can cause this message include the following:
  20674.  
  20675.  1. Compiling with the wrong include files. Typically, this involves
  20676.     compiling without the /I option, as described in MTDYNA.DOC.
  20677.  
  20678.  2. Compiling without defining the symbol DLL. DLL must be defined in
  20679.     any program that calls the C run-time library DLL.
  20680.  
  20681.  These options, as well as other important information, are covered in
  20682.  Section 5.2 of MTDYNA.DOC.
  20683.  
  20684.  
  20685.  462. Using a Wildcard Argument with the remove() Function
  20686.  
  20687.  Product Version(s): 5.10   | 5.10
  20688.  Operating System:   MS-DOS | OS/2
  20689.  Flags: ENDUSER | S_QuickC S_QuickASM
  20690.  Last Modified: 16-JAN-1990    ArticleIdent: Q48090
  20691.  
  20692.  Question:
  20693.  
  20694.  I'm using the remove() function to delete my files, but when I pass
  20695.  the wildcard as an argument, the function does not delete any files.
  20696.  Is there any why I can use the remove() function to delete all the
  20697.  files in the directory when I specify it to?
  20698.  
  20699.  Response:
  20700.  
  20701.  Yes; use the _dos_findfirst and _dos_findnext functions to search for
  20702.  each file and then use the remove() function to delete each file. The
  20703.  following example demonstrates how to write a code equivalent to
  20704.  remove("*.*"):
  20705.  
  20706.  Code Example
  20707.  ------------
  20708.  
  20709.  #include <stdio.h>
  20710.  #include <dos.h>
  20711.  #include <io.h>
  20712.  
  20713.  main ()
  20714.  {
  20715.     struct find_t  c_file;
  20716.     char fn[12];
  20717.  
  20718.     printf ("Enter file to delete: ");
  20719.     scanf ("%s", fn);
  20720.  
  20721.  /* This code section will delete all the files in the directory. */
  20722.     if (strcmp(fn, "*.*") == 0) {
  20723.       _dos_findfirst ("*.*", _A_NORMAL, &c_file);
  20724.       do {
  20725.              remove (c_file.name);
  20726.          } while (_dos_findnext (&c_file) == 0);
  20727.       }
  20728.     else
  20729.  
  20730.  /* This section will delete only one file. */
  20731.       if (remove (fn) == -1)
  20732.          printf ("File not found\n");
  20733.       else
  20734.          printf ("File successfully deleted\n");
  20735.  }
  20736.  
  20737.  
  20738.  463. Mixed-Language Examples for Calling Pascal Are Incorrect
  20739.  
  20740.  Product Version(s): 5.00 5.10 | 5.10
  20741.  Operating System:   MS-DOS    | OS/2
  20742.  Flags: ENDUSER | docerr H_MASM S_PasCal
  20743.  Last Modified: 16-JAN-1990    ArticleIdent: Q48251
  20744.  
  20745.  In the "Microsoft Mixed-Language Programming Guide" provided with C
  20746.  Versions 5.00 and 5.10, MASM Versions 5.00 and 5.10, and Pascal
  20747.  Version 4.00, there is a sample Pascal module that is incorrect. This
  20748.  module is called Pfun and it appears in three different sections of
  20749.  the manual. Pfun can be found in the following locations:
  20750.  
  20751.  1. Page 30, Section 2.5.2 "Calling Pascal from Basic -- Function Call"
  20752.  
  20753.  2. Page 44, Section 3.5.2 "Calling Pascal from C -- Function Call"
  20754.  
  20755.  3. Page 57, Section 4.5.2 "Calling Pascal from FORTRAN -- Function Call"
  20756.  
  20757.  If the Pascal source code shown on these pages is compiled, the
  20758.  following errors occur:
  20759.  
  20760.    21  7   begin
  20761.  = 22  8     Fact := Fact * n;
  20762.        8  --------------^Warning 171 Insert (
  20763.        8  ----------------^268 Cannot Begin Expression  Skipped
  20764.        8  -------------------^Warning 155 ; Assumed ,
  20765.        8  -------------------^257 Parameter List Size Wrong Begin Ski
  20766.  
  20767.  To get the code to compile correctly, all of the incorrect references
  20768.  to Fact must be removed and replaced by a temporary variable. The
  20769.  following source code contains the necessary changes to the Pfun
  20770.  module so that it will compile and run without any errors:
  20771.  
  20772.  module Pfun;
  20773.    function Fact (n : integer) : integer;
  20774.  
  20775.  {Integer parameters received by value, the Pascal default. }
  20776.  
  20777.    var   temp : integer;
  20778.  
  20779.    begin
  20780.       temp := 1;
  20781.       while n > 0 do
  20782.          begin
  20783.              temp := temp * n;
  20784.              n := n - 1;
  20785.          end;
  20786.       Fact := temp;
  20787.    end;
  20788.  end.
  20789.  
  20790.  Note: There is an incorrect reference to the errors in the Fact
  20791.  function in the Pascal Version 4.00 README.DOC file. This correction
  20792.  does not work.
  20793.  
  20794.  
  20795.  464. Mixed-Language Examples for Calling Fortran Are Incorrect
  20796.  
  20797.  Product Version(s): 5.00 5.10 | 5.10
  20798.  Operating System:   MS-DOS    | OS/2
  20799.  Flags: ENDUSER | docerr H_MASM S_PasCal
  20800.  Last Modified: 16-JAN-1990    ArticleIdent: Q48424
  20801.  
  20802.  In the "Microsoft Mixed-Language Programmer's Guide" provided with C
  20803.  Versions 5.00 and 5.10, MASM Versions 5.00 and 5.10, and Pascal
  20804.  Version 4.00, the C and Pascal sample programs for calling a FORTRAN
  20805.  subroutine are incorrect. The documentation error appears in two
  20806.  different sections of the manual. The documentation error may be found
  20807.  in the following locations:
  20808.  
  20809.  1. Page 40, Section 3.4.1, "Calling FORTRAN from C -- Subroutine Call"
  20810.  
  20811.  2. Page 67, Section 5.5.1, "Calling FORTRAN from Pascal -- Subroutine
  20812.     Call"
  20813.  
  20814.  The source code in the manual compiles, but when linked with the
  20815.  FORTRAN subroutine, the following error occurs:
  20816.  
  20817.     LINK : error L2029: Unresolved externals:
  20818.  
  20819.     MAXPAR in file(s):
  20820.      FACT.OBJ(fact.c)
  20821.  
  20822.     There was 1 error detected
  20823.  
  20824.  This error occurs because the FORTRAN subroutine has a different name
  20825.  than is used by the calling programs (maxparam instead of maxpar). To
  20826.  get the two modules to link correctly, the following changes must be
  20827.  made:
  20828.  
  20829.  In C (Page 40), change
  20830.  
  20831.     extern void fortran maxpar (int near *, int near *);
  20832.                  .
  20833.                  .
  20834.     maxpar (&a, &b);
  20835.  
  20836.  to the following:
  20837.  
  20838.     extern void fortran maxparam (int near *, int near *);
  20839.                  .
  20840.                  .
  20841.     maxparam (&a, &b);
  20842.  
  20843.  In Pascal (Page 67), change
  20844.  
  20845.     procedure Maxpar (var i,j : integer) ; extern;
  20846.                  .
  20847.                  .
  20848.     Maxpar (a,b);
  20849.  
  20850.  to the following:
  20851.  
  20852.     procedure Maxparam (var i,j : integer) ; extern;
  20853.                  .
  20854.                  .
  20855.     Maxparam (a,b);
  20856.  
  20857.  
  20858.  465. Macros ceil and floor Incorrectly Listed As Functions
  20859.  
  20860.  Product Version(s): 5.00 5.10 | 5.10
  20861.  Operating System:   MS-DOS    | OS/2
  20862.  Flags: ENDUSER | docerr
  20863.  Last Modified: 16-JAN-1990    ArticleIdent: Q48431
  20864.  
  20865.  Page 94, Section 3.3.13 of the "Microsoft C 5.1 Optimizing Compiler
  20866.  User's Guide" incorrectly lists ceil and floor as functions that have
  20867.  intrinsic forms.
  20868.  
  20869.  As correctly noted in the "Microsoft C 5.1 Optimizing Compiler
  20870.  Run-Time Library Reference" on Pages 152 and 270, ceil and floor are
  20871.  macros defined in the include file MATH.H.
  20872.  
  20873.  
  20874.  466. The Interrupt Attribute Pushes Registers on the Stack
  20875.  
  20876.  Product Version(s): 5.10
  20877.  Operating System:   MS-DOS
  20878.  Flags: ENDUSER | S_QuickC  S_QuickASM
  20879.  Last Modified: 16-JAN-1990    ArticleIdent: Q48444
  20880.  
  20881.  The interrupt attribute can be applied to a function to tell the
  20882.  compiler that the function is an interrupt handler.
  20883.  
  20884.  When an interrupt function is called, all registers (except SS) are
  20885.  saved on the stack. Examining the assembler code the compiler
  20886.  generates for an interrupt handler could cause confusion. When
  20887.  compiling without the /G1 or /G2 switch (these switches inform the
  20888.  compiler to generate 186 or 286 code accordingly) the assembler code
  20889.  appears as it should, however, when using one of the two
  20890.  aforementioned switches, the assembler output may be deceiving in that
  20891.  the registers appear as though they are not being saved on the stack
  20892.  as advertised.
  20893.  
  20894.  This potential misinterpretation results from the use of the PUSHA
  20895.  instruction, which does not exist in the 8086 instruction set, but
  20896.  does apply to the 80186 and more recent sets. The PUSHA instruction
  20897.  pushes the general purpose registers onto the stack in the following
  20898.  order: AX, CX, DX, BX, SP, BP, SI, DI.  For further information
  20899.  regarding the PUSHA instruction, you should consult an reference
  20900.  manual for Intel's 80x86-based assembly.
  20901.  
  20902.  The text that follows displays two partial assembler listings of an
  20903.  interrupt handler called foo. The second case demonstrates the usage
  20904.  of the 186, 286, 386 specific instruction PUSHA (for load all).
  20905.  
  20906.  /* Without G1 or G2 */
  20907.  
  20908.  _foo    PROC FAR
  20909.          push    ax
  20910.          push    cx
  20911.          push    dx
  20912.          push    bx
  20913.          push    sp
  20914.          push    bp
  20915.          push    si
  20916.          push    di
  20917.          push    ds
  20918.          push    es
  20919.  
  20920.   /* With G1 or G2 */
  20921.  
  20922.   _foo    PROC FAR
  20923.          pusha              ; This pushes all general purpose registers
  20924.          push    ds         ; for the 80186 processors and above.
  20925.          push    es
  20926.  
  20927.  
  20928.  467. How to Find the Total Stack Size from within a Program
  20929.  
  20930.  Product Version(s): 5.10   | 5.10
  20931.  Operating System:   MS-DOS | OS/2
  20932.  Flags: ENDUSER | SR# G890831-26299
  20933.  Last Modified: 16-JAN-1990    ArticleIdent: Q48686
  20934.  
  20935.  Question:
  20936.  
  20937.  How can I find the total size of the stack from within my program?
  20938.  
  20939.  Response:
  20940.  
  20941.  The program below calculates the total size of the stack. Note that
  20942.  this works slightly differently for protected-mode and bound programs
  20943.  than for real-mode programs. (Normally, the two-byte difference
  20944.  shouldn't be important.)
  20945.  
  20946.  The symbol "_end" is declared just below the lowest location in the
  20947.  stack. At any given time, the amount of space left on the stack is SP
  20948.  - offset _end. (The C program doesn't use the underscore because C
  20949.  automatically prepends an underscore to all identifiers.)
  20950.  
  20951.  The start-up code stores the maximum (initial) value of SP in the
  20952.  variable __atopsp. (The program below uses only one underscore rather
  20953.  than two for the reason described in the previous paragraph.)
  20954.  
  20955.  Default stack checking on function entry fails when the amount left is
  20956.  less than 256 bytes for DOS, or less than 512 bytes for OS/2. When
  20957.  stack checking fails, you receive the following run-time error:
  20958.  
  20959.     run-time error R6000
  20960.     - stack overflow
  20961.  
  20962.  The program to calculate the total stack size follows:
  20963.  
  20964.  #include <stdio.h>
  20965.  
  20966.  extern unsigned int end;
  20967.  
  20968.  extern unsigned int _atopsp;
  20969.  
  20970.  void main(void)
  20971.  {
  20972.      unsigned stksize;
  20973.  
  20974.      stksize = _atopsp - (unsigned)&end + 2;
  20975.          /* don't add 2 for protected-mode or bound programs */
  20976.  
  20977.      printf("Total stack size is %u bytes (%x hex bytes)\n",
  20978.          stksize, stksize);
  20979.  }
  20980.  
  20981.  
  20982.  468. int86x() and int86() Trap for Interrupts 25h, 26h
  20983.  
  20984.  Product Version(s): 5.00 5.10
  20985.  Operating System:   MS-DOS
  20986.  Flags: ENDUSER | S_QuickC S_QuickASM
  20987.  Last Modified: 16-JAN-1990    ArticleIdent: Q48744
  20988.  
  20989.  Interrupts 25h (absolute disk read) and 26h (absolute disk write)
  20990.  require special handling when being used because they leave the CPU
  20991.  flags on the stack upon termination.
  20992.  
  20993.  Functions int86x() and int86() work reliably with these interrupts.
  20994.  The int86() functions trap for these two interrupts, and take care of
  20995.  the stack appropriately. Use one of the int86() functions to make
  20996.  these calls as you would any other DOS interrupt call. You need take no
  20997.  extra precautions with these interrupts.
  20998.  
  20999.  The following example demonstrates the straight-forwardness of the
  21000.  function call:
  21001.  
  21002.  #include <stdio.h>
  21003.  #include <dos.h>
  21004.  #include <malloc.h>
  21005.  
  21006.  /*****            WARNING!!!!!          ******/
  21007.  /* If you change the following line so that DRIVE_A is assigned a 2 or
  21008.     above, you could destroy data on your hard drive. This test program
  21009.     segment was written to read and write from the floppy disk A:        */
  21010.  #define DRIVE_A 0                    /* 0=A, 1=B, 2=C, etc. */
  21011.  #define ONE_SECTOR 1
  21012.  #define ABS_WRITE 38                 /* Decimal value of int call */
  21013.  #define ABS_READ 37                  /* Decimal value of int call */
  21014.  unsigned int far *out;               /* Pointer to Data to be output */
  21015.  unsigned int far *input;             /* Pointer to Data Transfer Area */
  21016.  unsigned int output;                 /* Data to be output */
  21017.  union REGS inregs, outregs;
  21018.  struct SREGS segregs;
  21019.  
  21020.  void main(void)  {
  21021.     out = &output;
  21022.     input = (unsigned int far *) malloc (1024 * sizeof(unsigned int));
  21023.     *out = 11;
  21024.     inregs.h.al = DRIVE_A;              /* Write to Drive A */
  21025.     inregs.x.cx = ONE_SECTOR;           /* Write one sector only */
  21026.     inregs.x.dx = 3;                    /* Logical sector 3 */
  21027.     segregs.ds = FP_SEG(out);           /* Get Seg address of output */
  21028.     inregs.x.bx = FP_OFF(out);          /* Get Offset of output */
  21029.     outregs.x.ax = 0;                   /* No error */
  21030.     int86x (ABS_WRITE, &inregs, &outregs, &segregs);
  21031.  
  21032.     inregs.h.al = DRIVE_A;              /* Read to Drive A */
  21033.     inregs.x.cx = ONE_SECTOR;           /* Read one sector only */
  21034.     inregs.x.dx = 3;                    /* Logical sector 3 */
  21035.     segregs.ds = FP_SEG(input);         /* Get Seg address of buffer */
  21036.     inregs.x.bx = FP_OFF(input);        /* Get Offset of buffer */
  21037.     outregs.x.ax = 0;                   /* No error */
  21038.     int86x (ABS_READ, &inregs, &outregs, &segregs);
  21039.     printf ("%u was read from drive A: \n", *input);
  21040.  }
  21041.  
  21042.  
  21043.  469. Potential Problems with Identifiers Over 31 Characters
  21044.  
  21045.  Product Version(s): 5.00 5.10 | 5.10
  21046.  Operating System:   MS-DOS    | OS/2
  21047.  Flags: ENDUSER | S_QuickC S_QuicKASM
  21048.  Last Modified: 16-JAN-1990    ArticleIdent: Q48790
  21049.  
  21050.  The #define statement in Microsoft C accepts identifiers up to 31
  21051.  characters. The compiler truncates identifiers over 31 characters, and
  21052.  on warning level 1 or greater, produces the following warning message:
  21053.  
  21054.     warning C4011: identifier truncated to '<truncated identifier>'
  21055.  
  21056.  This can cause potential problems if two or more identifiers are
  21057.  identical up to the 31st character. If this is the case, the following
  21058.  warning message appears for each additional #define that is identical
  21059.  when truncated (on warning levels 1 or greater):
  21060.  
  21061.     warning C4005: '<truncated identifier>' : redefinition
  21062.  
  21063.  All of these identifiers are assigned the value of the last identifier
  21064.  that was identical when truncated.
  21065.  
  21066.  This information also applies to QuickC Versions 1.01, 2.00, 2.01 and
  21067.  QuickAssembler Version 2.01.
  21068.  
  21069.  
  21070.  470. Include Filenames More Than Eight Characters Are Truncated
  21071.  
  21072.  Product Version(s): 5.00 5.10 | 5.10
  21073.  Operating System:   MS-DOS    | OS/2
  21074.  Flags: ENDUSER | S_QuickC S_QuickASM
  21075.  Last Modified: 16-JAN-1990    ArticleIdent: Q48792
  21076.  
  21077.  When given a filename that is more than eight characters, the file
  21078.  system under MS-DOS truncates the filename to eight characters.
  21079.  Because of this, the following include statement
  21080.  
  21081.     #include <gefildefish.h>
  21082.  
  21083.  looks for the following header file to resolve the reference:
  21084.  
  21085.     gefildef.h
  21086.  
  21087.  As long as the file gefildef.h is found on the disk, no error or
  21088.  warning message is displayed.
  21089.  
  21090.  Under OS/2 Version 1.10, however, the file system does not truncate
  21091.  names, but filenames with more than eight characters are not used.
  21092.  Therefore, the following fatal error message appears when specifying
  21093.  an include file with more than characters:
  21094.  
  21095.     C1015: cannot open include file '<filename>'
  21096.  
  21097.  This problem also occurs in QuickC Versions 1.01, 2.00, 2.01 and
  21098.  QuickAssembler Version 2.01.
  21099.  
  21100.  
  21101.  471. exec() and spawn() with P_OVERLAY Ignore Maximum Allocation
  21102.  
  21103.  Product Version(s): 5.10
  21104.  Operating System:   MS-DOS
  21105.  Flags: ENDUSER | S_QuickC S_QuickASM
  21106.  Last Modified: 16-JAN-1990    ArticleIdent: Q48793
  21107.  
  21108.  Exec() and spawn() with P_OVERLAY ignore the maximum memory allocation
  21109.  information in the .EXE file header. If you exec or spawn with
  21110.  P_OVERLAY, a program whose maximum allocation is set equal to the
  21111.  minimum allocation (through EXEMOD or the LINK option /CP:1), the
  21112.  program is allocated the full 64K DGROUP.
  21113.  
  21114.  The effective maximum allocation for any exec'ed (or spawn'ed with
  21115.  P_OVERLAY) program is 0xffff (whatever DOS has available), regardless
  21116.  of the maximum allocation number in the program's .EXE header. When
  21117.  run from the DOS prompt, the maximum allocation information of the
  21118.  same program is honored.
  21119.  
  21120.  This behavior occurs because the exec() and spawn() with P_OVERLAY
  21121.  functions do not invoke COMMAND.COM, which looks at the minalloc and
  21122.  maxalloc fields in the exe header. This is expected behavior for
  21123.  exec() and spawn() with P_OVERLAY in C Versions 4.00, 5.00, and 5.10,
  21124.  and QuickC 1.00, 1.01, 2.00, and 2.01 (QuickAssembler), as documented
  21125.  in the C 5.10 README.DOC on Line 1275, in the run-time library notes
  21126.  section for the exec() functions.
  21127.  
  21128.  Alternatives
  21129.  ------------
  21130.  
  21131.  Instead of calling a program with exec() or spawn() with P_OVERLAY,
  21132.  call COMMAND.COM with the desired child program as an argument using
  21133.  exec() or spawn() with P_OVERLAY, as follows:
  21134.  
  21135.  spawnl(P_OVERLAY,"c:\\command.com","command.com","/c child.exe",NULL);
  21136.  
  21137.  COMMAND.COM then loads your application as if it was from the DOS
  21138.  prompt. Note, however, that the COMMAND.COM shell itself requires
  21139.  approximately 4K. Also, consecutive exec() or spawn() with P_OVERLAY
  21140.  calls using this method run additional shells of COMMAND.COM,
  21141.  accumulating one 4K shell per generation, as illustrated below:
  21142.  
  21143.            +------+    +------+    +------+    +------+
  21144.            |  P1  |--> |__P2__|--> |__P3__|--> |__P4__|
  21145.            +------+    | .COM |    |_.COM_|    |_.COM_|
  21146.                        +------+    | .COM |    |_.COM_|
  21147.                                    +------+    | .COM |
  21148.                                                +------+
  21149.  
  21150.  Another option is to call your program with the system() function, but
  21151.  this does not overlay the child process.
  21152.  
  21153.  Additional reference words: execl execle execlp execlpe execcv execve
  21154.  execvp execvpe spawnl spawnle spawnlp spawnlpe spawnv spawnve spawnvp
  21155.  spawnvpe
  21156.  
  21157.  
  21158.  472. Newline Character (\n) Is Equivalent to ASCII Linefeed (0x0A)
  21159.  
  21160.  Product Version(s): 5.00 5.10  | 5.00 5.10
  21161.  Operating System:   MS-DOS     | OS/2
  21162.  Flags: ENDUSER | S_QuickC S_QuickAsm
  21163.  Last Modified: 16-JAN-1990    ArticleIdent: Q48885
  21164.  
  21165.  The newline character in Microsoft C (\n) is equivalent to the ASCII
  21166.  linefeed character (hex 0A). Thus, for files opened in text mode,
  21167.  CR/LF pairs are read in as newline characters, and newline characters
  21168.  are written as CR/LF.
  21169.  
  21170.  This information applies to STDIN, STDOUT, and STDERR, which are
  21171.  opened in text mode by default.
  21172.  
  21173.  When using strtok() to extract tokens separated by CR/LF in a file
  21174.  opened in text mode, only \n must be used as a token delimiter.
  21175.  
  21176.  
  21177.  473. Cast of Float to Long Truncates Value to 1 Less Than Expected
  21178.  
  21179.  Product Version(s): 5.10   | 5.10
  21180.  Operating System:   MS-DOS | OS/2
  21181.  Flags: ENDUSER | S_QuickC S_QuickAsm
  21182.  Last Modified:  7-DEC-1989    ArticleIdent: Q48928
  21183.  
  21184.  Question:
  21185.  
  21186.  When I cast a float to a long integer, the result is one less than the
  21187.  expected value.
  21188.  
  21189.  The following is an example:
  21190.  
  21191.     double i, j;
  21192.     char  r[] = "16.49";
  21193.  
  21194.     i = atof(r) * 100;
  21195.     printf ("%ld\n", (long)i);
  21196.  
  21197.  What causes this code to produce 1648 instead of 1649?
  21198.  
  21199.  Response:
  21200.  
  21201.  When a float or double value is converted to an integer number, the
  21202.  value is truncated. You are getting 1648 and not 1649 because the
  21203.  float value is not stored exactly as 1649.0000. The value is stored as
  21204.  1648.99999...999. When you cast the double value to a long integer,
  21205.  the number is truncated at the decimal point to 1648.
  21206.  
  21207.  This is expected behaviour for C Version 5.10, QuickC Versions 1.01
  21208.  and 2.00, and QuickC with QuickAssembler Version 2.01.
  21209.  
  21210.  The workaround for this constraint is to add 0.5 to the double value
  21211.  before converting to an integer value. The following code produces the
  21212.  correct result:
  21213.  
  21214.  Sample Code
  21215.  -----------
  21216.  
  21217.  #include <stdio.h>
  21218.  #include <math.h>
  21219.  
  21220.  double i, j;
  21221.  char  r[] = "16.49";
  21222.  
  21223.  main ()
  21224.  {
  21225.          i = atof(r) * 100;
  21226.          printf ("%ld\n", (long)(i + 0.5));
  21227.  }
  21228.  
  21229.  
  21230.  474. qsort() Appears Extremely Slow in Worst-Case Situations
  21231.  
  21232.  Product Version(s): 5.00 5.10 | 5.10
  21233.  Operating System:   MS-DOS    | OS/2
  21234.  Flags: ENDUSER | S_QuickC
  21235.  Last Modified: 16-JAN-1990    ArticleIdent: Q48965
  21236.  
  21237.  Question:
  21238.  
  21239.  When using qsort() in a worst-case situation (e.g. the array is
  21240.  already sorted in reverse order), the qsort() library routine appears
  21241.  to take an extremely long time. Have I done something wrong in my
  21242.  program or does a problem exist with Microsoft's qsort() algorithm?
  21243.  
  21244.  Response:
  21245.  
  21246.  The qsort() routine that was provided by Microsoft was optimized for
  21247.  both speed and stack usage [stack space is important because qsort()
  21248.  is heavily recursive]. Therefore, in a worst-case situation, which
  21249.  could recurse up to the number of elements in the list, qsort()
  21250.  sacrifices speed for stack space. This behavior allows larger lists to
  21251.  be sorted without stack overflow problems. Furthermore, Microsoft's
  21252.  qsort() routine is very competitive in sorting random files, the type
  21253.  of array for which quick sorts are designed.
  21254.  
  21255.  If used judiciously, Microsoft's qsort() is a very effective sort
  21256.  routine. In worst-case situations, Microsoft's qsort() is slower than
  21257.  some other sorting routines, but successfully sorts larger arrays
  21258.  without stack overflow problems.
  21259.  
  21260.  Microsoft is researching this problem and will post new information as
  21261.  it becomes available.
  21262.  
  21263.  
  21264.  475. Confusion Regarding the /Zs Switch
  21265.  
  21266.  Product Version(s): 5.00 5.10 | 5.10
  21267.  Operating System:   MS-DOS    | OS/2
  21268.  Flags: ENDUSER | S_QuickC S_QuickAsm
  21269.  Last Modified: 16-JAN-1990    ArticleIdent: Q48967
  21270.  
  21271.  The /Zs switch instructs the compiler to scan your code and check for
  21272.  syntax errors. This switch does not generate any code. Switches that
  21273.  assume code will be generated do not have any effect when used in
  21274.  conjunction with /Zs.
  21275.  
  21276.  Therefore, if you are using the /Zs switch and are unaware of the fact
  21277.  that it does not generate any code, it may appear that other switches,
  21278.  such as the /Fa switch, which generates an assembly listing, do not
  21279.  function.
  21280.  
  21281.  
  21282.  476. DOS APPEND Is Not Utilized with access() Function
  21283.  
  21284.  Product Version(s): 4.00 5.00 5.10
  21285.  Operating System:   MS-DOS
  21286.  Flags: ENDUSER | S_QuickC
  21287.  Last Modified: 16-JAN-1990    ArticleIdent: Q49006
  21288.  
  21289.  The Microsoft C run-time library function, access(), determines
  21290.  whether or not a specified file exists and can be accessed in read
  21291.  and/or write mode(s). The access() function searches the current
  21292.  working directory for the particular file or the directory specified
  21293.  by a path to the file.
  21294.  
  21295.  The DOS APPEND command, which establishes a search path for data files
  21296.  and works similarly to the PATH environment variable, appears to be a
  21297.  way to assist access() in finding files outside the current working
  21298.  directory without having to supply a path. However, the APPEND command
  21299.  does not search the data path when locating a file to be used by the
  21300.  access() function. Consequently, access() fails when searching for a
  21301.  file issued with no path and that is not in the current working
  21302.  directory.
  21303.  
  21304.  As documented in the "Microsoft MS-DOS User's Guide and User's
  21305.  Reference" on Page 30, APPEND searches the data path for all files
  21306.  with only the following MS-DOS system calls:
  21307.  
  21308.     Code          Function
  21309.     ----          --------
  21310.  
  21311.     0FH           Open File (FCB)
  21312.     23H           Get (FCB) File Size
  21313.     3DH           Open Handle
  21314.     11H           FCB search first  (with /x switch only)
  21315.     4EH           Handle find first (with /x switch only)
  21316.     4BH           Exec (with /x switch only)
  21317.  
  21318.  The access() function makes an MS-DOS system call to interrupt 21H
  21319.  function 43H, which sets and retrieves file attributes. Since this is
  21320.  not a system call listed above, APPEND does not perform file
  21321.  searching.
  21322.  
  21323.  The following program illustrates the APPEND limitation. The program
  21324.  uses access() to determine whether the file named TEST exists. Assume
  21325.  that the TEST data file is not in the current working directory, but
  21326.  instead is in a directory called c:\foo, and that the APPEND command
  21327.  "APPEND=c:\foo" was issued previously to set the appropriate search
  21328.  path.
  21329.  
  21330.  Sample Program
  21331.  --------------
  21332.  
  21333.  #include <io.h>
  21334.  #include <fcntl.h>
  21335.  #include <stdio.h>
  21336.  
  21337.  FILE * stream;
  21338.  
  21339.  void main( void )
  21340.  {
  21341.    /* check for existence of TEST fails despite having APPEND set */
  21342.    if ((access( "TEST", 0 )) == -1 )
  21343.    {
  21344.          printf( "file was not found with APPEND set\n\n" );
  21345.  
  21346.    /* however, fopen() recognizes APPEND for successful access */
  21347.          if ((stream = fopen( "TEST", "r")) != NULL )
  21348.              printf( "file opened successfully using APPEND" );
  21349.    }
  21350.  }
  21351.  
  21352.  
  21353.  477. Declaring a Pointer to a Function: C4071
  21354.  
  21355.  Product Version(s): 5.10
  21356.  Operating System:   MS-DOS
  21357.  Flags: ENDUSER | S_QuickC S_QuickAsm
  21358.  Last Modified: 16-JAN-1990    ArticleIdent: Q49064
  21359.  
  21360.  The following usual method of declaring a pointer to a function
  21361.  
  21362.     type (*ptr)();
  21363.     ptr = function;
  21364.  
  21365.  causes the following compiler warning when compiling with the "/W3"
  21366.  option:
  21367.  
  21368.     C4071: 'ptr' : no function prototype given
  21369.  
  21370.  Use one of the following methods to avoid the error message:
  21371.  
  21372.  1. Use the warning level flag "/W2" instead of "/W3".
  21373.  
  21374.  2. Prototype the function itself and then specify actual parameters
  21375.     when declaring the pointer, as follows:
  21376.  
  21377.        type (*ptr)(parameter_list);
  21378.        ptr = function;
  21379.  
  21380.  Note: The parameter list must be exactly the same parameter list with
  21381.  which the function was declared.
  21382.  
  21383.  The following program compiles and links with NO warnings when
  21384.  compiling with the '/W3' warning level flag set:
  21385.  
  21386.  /*  Must have 'stdio.h' to prototype 'printf' */
  21387.  #include <stdio.h>
  21388.  
  21389.  void main (void)
  21390.  {
  21391.     /* Declare 'fun_ptr' as a pointer to a function  */
  21392.     int (*fun_ptr)(const char *, ...);
  21393.     int other_args;
  21394.  
  21395.     /* Assign pointer to the specific function, 'printf' */
  21396.     fun_ptr = printf;
  21397.  
  21398.     /* Standard usage in calling environment */
  21399.     fun_ptr("format string goes here", other_args);
  21400.  }
  21401.  
  21402.  
  21403.  478. Error in Run-Time Reference to _getcursorposition
  21404.  
  21405.  Product Version(s): 5.10
  21406.  Operating System:   MS-DOS
  21407.  Flags: ENDUSER | docerr S_QuickC S_QuickASM
  21408.  Last Modified: 16-JAN-1990    ArticleIdent: Q49428
  21409.  
  21410.  Appendix B of the "Microsoft C Run-Time Library Reference" and
  21411.  "Microsoft QuickC Run-Time Library Reference" lists routines that are
  21412.  specific to MS-DOS. The lists in both references refer to the
  21413.  _getcursorposition routine. The routine referred to should be
  21414.  _getcurrentposition.
  21415.  
  21416.  The error can be found in the C run-time library reference on Page
  21417.  655. The same error is found on Page 655 of the QuickC Versions 1.00
  21418.  and 1.01 run-time library reference. This manual is sent upon request
  21419.  to QuickC 2.00 or 2.01 customers who desire a hard copy of the
  21420.  reference.
  21421.  
  21422.  The list shown in Appendix B in the manuals is not included in the
  21423.  QuickC 2.00 and 2.01 on-line help references.
  21424.  
  21425.  
  21426.  479. Ftime: C Function -- Documentation Supplement
  21427.  
  21428.  Product Version(s): 5.10
  21429.  Operating System:   MS-DOS
  21430.  Flags: ENDUSER | S_QuickC S_QuickASM docsup
  21431.  Last Modified: 17-JUL-1990    ArticleIdent: Q49501
  21432.  
  21433.  The ftime function takes a pointer to a timeb structure as its only
  21434.  parameter and has no return value. Ftime calculates the current time
  21435.  and returns it by modifying the timeb structure. The structure
  21436.  contains the following elements in the given order:
  21437.  
  21438.  Name      Type           Description
  21439.  ----      ----           -----------
  21440.  
  21441.  time      time_t(long)   The time in seconds since 00:00:00 Greenwich
  21442.                           mean time, January 1, 1970. This time is
  21443.                           calculated under MS-DOS by calling Int 21,
  21444.                           function 2Ah (Get Date), converting the
  21445.                           results to seconds, and adding the current
  21446.                           time, which is also converted to seconds.
  21447.  
  21448.  millitm   USHORT         Fraction of a second in milliseconds. This
  21449.                           value is actually not milliseconds on most
  21450.                           systems. On most IBM PCs and compatibles, the
  21451.                           clock speed is not fast enough to compute
  21452.                           milliseconds, or indeed, hundredths of
  21453.                           seconds. The ftime function calls interrupt
  21454.                           21, function 2Ch (under DOS), which returns,
  21455.                           among other information, the seconds in
  21456.                           hundredths. The hundredths information is an
  21457.                           estimation based on the clock speed, which is
  21458.                           approximately 18.2 ticks per second on most
  21459.                           PCs. The hundredths value is then multiplied
  21460.                           by ten to get the millisecond value.
  21461.  
  21462.  timezone  short          The difference in minutes, moving westward,
  21463.                           between Greenwich mean time and local time.
  21464.                           This is equal to the global variable
  21465.                           timezone, from a call to the tzset function.
  21466.  
  21467.  dstflag   short          This flag is nonzero if daylight savings
  21468.                           time (DST) is currently in effect for the local
  21469.                           time zone. This is done by a call to the
  21470.                           internal function _isindst. This function
  21471.                           takes a timeb structure as a parameter and
  21472.                           returns an integer flag. This is the rule for
  21473.                           years before 1987; a time is in DST if it is
  21474.                           on or after 02:00:00 on the last Sunday in
  21475.                           April and before 01:00:00 on the last Sunday
  21476.                           in October. This is the rule for years
  21477.                           starting with 1987; a time is in DST if it
  21478.                           is on or after 02:00:00 on the first Sunday
  21479.                           in April and before 01:00:00 on the last
  21480.                           Sunday in October. (See tzset for more
  21481.                           information on DST.)
  21482.  
  21483.  Other sources of information include the Version 5.10 "Microsoft C for the
  21484.  MS-DOS Operating System: Run-Time Library Reference," Pages 308-9 and
  21485.  the ftime function in the "C Run-Time Library Source Routines".
  21486.  
  21487.  
  21488.  480. sscanf with %i and a Leading 0 Gives Octal Conversion Results
  21489.  
  21490.  Product Version(s): 5.10   | 5.10
  21491.  Operating System:   MS-DOS | OS/2
  21492.  Flags: ENDUSER | S_QuickC S_QuickASM scanf sscanf fscanf
  21493.  Last Modified: 22-NOV-1989    ArticleIdent: Q49573
  21494.  
  21495.  Question:
  21496.  
  21497.  Why does sscanf return incorrect results when I use the %i switch, yet
  21498.  it returns correct results when I use the %d switch?
  21499.  
  21500.  Response:
  21501.  
  21502.  The %i switch has the capability of reading in decimal, octal, and
  21503.  hexadecimal numbers. Hexadecimal numbers are specified with the 0x in
  21504.  front of the number, while octal numbers are specified with the 0
  21505.  (zero) in front of them. If you want only decimal numbers to be read
  21506.  in, use the %d switch.
  21507.  
  21508.  This is expected behavior and occurs with the entire scanf family.
  21509.  
  21510.  
  21511.  481. Inconsistent Use of fscanf %x.xf Formatting May Produce Errors
  21512.  
  21513.  Product Version(s): 5.10   | 5.10
  21514.  Operating System:   MS-DOS | OS/2
  21515.  Flags: ENDUSER | S_C S_QuickC
  21516.  Last Modified: 17-JUL-1990    ArticleIdent: Q49823
  21517.  
  21518.  Using the Microsoft C 5.10 run-time library function fscanf() with the
  21519.  format specifier %x.xf to read floating-point values usually produces
  21520.  undesirable results. This happens especially if the file contains
  21521.  floating point information that was not recorded using the same %x.x
  21522.  specifier that is being used to read.
  21523.  
  21524.  This is not a problem with the fscanf() function (see below).
  21525.  
  21526.  The following code can be used as an example of expected behavior:
  21527.  
  21528.  #include<stdio.h>
  21529.  
  21530.  void main( void )
  21531.  {
  21532.     float a = 3.104f, b = 34.23534f, c = 834.3432f, d = 5968.394f;
  21533.     float e = 34253.2f;
  21534.     float ar, br, cr, dr, er;
  21535.     FILE *stream;
  21536.  
  21537.     if( (stream = fopen( "file.tst", "a" )) == NULL )
  21538.        printf( "ERROR:  Unable to open output file" );
  21539.     else
  21540.        fprintf( stream, "%f,%f,%f,%f,%f\n", a, b, c, d, e );
  21541.     fclose( stream );
  21542.     if( (stream = fopen( "file.tst", "r" )) == NULL )
  21543.        printf( "ERROR:  Unable to open input file" );
  21544.     else
  21545.                      /* NOTE:  %x.x format specifier */
  21546.     {                /*  |  */
  21547.        printf("Values: %2.4f, %f, %f, %f, %f\n", a, b, c, d, e );
  21548.        fscanf( stream, "%4f,%4f,%4f,%4f,%4f", &ar, &br, &cr, &dr, &er);
  21549.        printf("After Read: %f, %f, %f, %f, %f\n", ar, br, cr, dr, er );
  21550.     }
  21551.  }
  21552.  
  21553.  The output from the program is as follows:
  21554.  
  21555.     Values: 3.104000, 34.235340, 834.343201, 5968.394043
  21556.     After Read: 3.1000, 0.000000, 0.000000, 0.000000
  21557.  
  21558.  The unwanted behavior is obvious, as the "Values" above are what is
  21559.  contained in the output file "file.tst" and these are definitely not
  21560.  the values that are read back in.
  21561.  
  21562.  However, this is not a problem with the fscanf() function. The first
  21563.  value is read in correctly. After the first value is read, the file
  21564.  pointer points to the second 0 (zero) in 3.104000. When the second
  21565.  value is read, the information in the file does not conform to
  21566.  floating-point format, and zeros are read after that. The compiler has
  21567.  no way of knowing how far to move the file pointer to get to the next
  21568.  value.
  21569.  
  21570.  If the %2.4f in the fscanf() line in the code above were replaced by
  21571.  %f, the program output would be as follows:
  21572.  
  21573.     Values:     3.104000, 34.235340, 834.343201, 5968.394043
  21574.     After Read: 3.104000, 34.235340, 834.343201, 5968.394043
  21575.  
  21576.  To read truncated or formatted floating-point values from a file, use
  21577.  the %f format specifier and modify the values after they are read.
  21578.  
  21579.  
  21580.  482. Use of the /Gt Switch in C
  21581.  
  21582.  Product Version(s): 5.10   | 5.10
  21583.  Operating System:   MS-DOS | OS/2
  21584.  Flags: ENDUSER |
  21585.  Last Modified:  7-DEC-1989    ArticleIdent: Q49840
  21586.  
  21587.  Question:
  21588.  
  21589.  I am using large memory model and the /Gt switch when programming and
  21590.  I still get the message "stack plus data larger than 64K." Could you
  21591.  give me some pointers about where data goes when using large model? Do
  21592.  heap and stack still remain in DGROUP when I use /Gt?
  21593.  
  21594.  Response:
  21595.  
  21596.  What goes out of the default data segment depends on how you use /Gt.
  21597.  /Gt alone is the same as /Gt256, which means that ONLY data items of
  21598.  size 256 and greater get moved out. If you have a lot of data items
  21599.  smaller than that, that data will NOT get moved out. With /Gt256, it
  21600.  is still possible that the data left in DGROUP plus the stack could
  21601.  exceed 64K.
  21602.  
  21603.  As the value on the /Gt switch becomes smaller, more and more data
  21604.  gets pushed out. /Gt0 pushes all of the data generated by your program
  21605.  out. However, it also generates some constants in the logical segment
  21606.  _CONST in DGROUP, 2 bytes for each extern or uninitialized variable
  21607.  moved. The following classes of variables will generate a 2-byte
  21608.  segment address in DGROUP for EACH variable of that class declared
  21609.  when /Gt0 is used:
  21610.  
  21611.  1. All extern declarations, such as "extern int i;"
  21612.  
  21613.  2. All declarations without storage class that are not initialized,
  21614.     such as "int i;"
  21615.  
  21616.  Initialized variables such as "int i = 0;", provided that the sum of
  21617.  their sizes is less then 64K, are treated as a group and generate only
  21618.  one segment address in DGROUP per module. Therefore, the optimal
  21619.  number for minimizing DGROUP space is /Gt3. /Gt3 is better than /Gt0
  21620.  for uninitialized and extern variables because /Gt0 will move out 1-
  21621.  and 2-byte data elements to the far heap, replacing them with 2-byte
  21622.  segment addresses. Not only does this NOT save you space in DGROUP
  21623.  V.S. /Gt3, but it will increase the overall size of the executable
  21624.  V.S. /Gt3 as you also have to pay 2 bytes in the far heap per data
  21625.  element moved. Another reason to use /Gt3 over /Gt0 is that although
  21626.  the size of DGROUP will remain the same, /Gt0 will cause character and
  21627.  integer data elements to be addressed with far pointers, slowing
  21628.  execution. With /Gt0, all that remains in DGROUP is the stack, several
  21629.  kilobytes of variables associated with the run-time library, the near
  21630.  heap (from which will be allocated some file buffers and the local
  21631.  copy of the environment), and the 2-byte segment addresses for data
  21632.  items moved out as needed.
  21633.  
  21634.  
  21635.  483. Installing In-Line 80 x 87 Assembly Instructions
  21636.  
  21637.  Product Version(s): 5.10
  21638.  Operating System:   MS-DOS
  21639.  Flags: ENDUSER | docerr appnote
  21640.  Last Modified: 16-JAN-1990    ArticleIdent: Q49842
  21641.  
  21642.  The assembler code on Page 168 of the "Microsoft C Optimizing Compiler
  21643.  User's Guide," Version 5.10, is incorrect. When assembled and linked
  21644.  with your C application, this code will cause divide by zero and
  21645.  overflows to be masked.
  21646.  
  21647.  This behavior occurs because the code on Page 168 is incomplete. The
  21648.  correct code is listed below. Case is important, so assemble with the
  21649.  -Mx switch. You should also link with the /NOE switch. This code is
  21650.  provided to produce in-line 8087 instructions on FORTRAN Versions 4.x
  21651.  and C Versions 5.x.
  21652.  
  21653.  This application note is also available from Microsoft Product Support
  21654.  Services by calling (206) 454-2030.
  21655.  
  21656.  ;************************************************************************
  21657.  ;rmfixups.asm -
  21658.  ;
  21659.  ;   Copyright (c) 1988-1988, Microsoft Corporation.  All Rights Reserved.
  21660.  ;
  21661.  ;Purpose:
  21662.  ;  Link with rmfixups.obj in order to prevent floating point instructions
  21663.  ;  from being fixed up.
  21664.  ;  The case of these names is important so assemble with the -Mx switch.
  21665.  ;
  21666.  ;*************************************************************************
  21667.  
  21668.  public  FIWRQQ,FIERQQ,FIDRQQ,FISRQQ,FJSRQQ,FIARQQ,FJARQQ,FICRQQ,FJCRQQ
  21669.  
  21670.  FIDRQQ  EQU     0
  21671.  FIERQQ  EQU     0
  21672.  FIWRQQ  EQU     0
  21673.  FIARQQ  EQU     0
  21674.  FJARQQ  EQU     0
  21675.  FISRQQ  EQU     0
  21676.  FJSRQQ  EQU     0
  21677.  FICRQQ  EQU     0
  21678.  FJCRQQ  EQU     0
  21679.  
  21680.  extrn   __fpmath:far
  21681.  extrn   __fptaskdata:far
  21682.  extrn   __fpsignal:far
  21683.  
  21684.  CDATA   segment word common 'DATA'
  21685.          dw      0
  21686.          dd      __fpmath
  21687.          dd      __fptaskdata
  21688.          dd      __fpsignal
  21689.  CDATA   ends
  21690.  
  21691.  end
  21692.  
  21693.  
  21694.  484. Mixing Case of LINK Option Causes Error L1093 or D4002
  21695.  
  21696.  Product Version(s): 5.10   | 5.10
  21697.  Operating System:   MS-DOS | OS/2
  21698.  Flags: ENDUSER | S_QuickC
  21699.  Last Modified: 30-NOV-1989    ArticleIdent: Q49871
  21700.  
  21701.  When specifying linker options from the CL or the QCL command line,
  21702.  the word "link" must be all lowercase letters. If the word "link" is
  21703.  not all lowercase, the error that occurs is either:
  21704.  
  21705.     Command line warning D4002 : ignoring unknown flag '-xxxx'
  21706.  
  21707.     or
  21708.  
  21709.     LINK : fatal error L1093: xxxx.OBJ : object not found
  21710.  
  21711.  Note: xxxx is the four letters keyed in after the "/" (forward slash)
  21712.  or the "-" (hyphen).
  21713.  
  21714.  For example, issuing the following command from the MS-DOS or OS/2
  21715.  command prompt
  21716.  
  21717.     cl file.c /Link graphics.lib
  21718.  
  21719.  produces the following error:
  21720.  
  21721.     Command line warning D4002 : ignoring unknown flag '-Link'
  21722.  
  21723.  
  21724.  485. Fread() Can Read More Than 64K at a Time
  21725.  
  21726.  Product Version(s): 5.10   | 5.10
  21727.  Operating System:   MS-DOS | OS/2
  21728.  Flags: ENDUSER | S_QuickC
  21729.  Last Modified: 30-NOV-1989    ArticleIdent: Q49872
  21730.  
  21731.  It is possible to read more than 64K at a time with the fread()
  21732.  function by specifying an item size greater than 1 and a count from 1
  21733.  to 64K. The resulting number of bytes read will be the product of size
  21734.  and count.
  21735.  
  21736.  The follow code demonstrates how to read a file 200K in length:
  21737.  
  21738.  /* Must be compiled in huge memory model */
  21739.  #include <stdio.h>
  21740.  
  21741.  char huge buffer[205000];
  21742.  
  21743.  void main(void)
  21744.  {
  21745.       FILE *fp;
  21746.  
  21747.       fp=fopen("testfile.dat","r");
  21748.  
  21749.       fread(buffer,4,51200,fp);     /* 51200*4=204,800 */
  21750.  
  21751.      /* The value returned from the line above will be the number of
  21752.         items read. This number is limited to 64K because it is of
  21753.         type size_t. But remember, the total number of bytes read is
  21754.         equal to the number of items times the size of each item, which
  21755.         is 4 bytes in this case. Therefore, the total bytes read
  21756.         is 4 times 51200 or 204,800 bytes. */
  21757.  }
  21758.  
  21759.  
  21760.  486. /Ol Causes Constant Overflow Warnings c4057 c4056
  21761.  
  21762.  Product Version(s): 5.00 5.10 | 5.10
  21763.  Operating System:   MS-DOS    | OS/2
  21764.  Flags: ENDUSER |
  21765.  Last Modified: 17-JUL-1990    ArticleIdent: Q50251
  21766.  
  21767.  The following small program, when compiled with loop optimization
  21768.  (/Ol), produces the following warnings on the auto-decrement statement
  21769.  in the second for loop:
  21770.  
  21771.     warning C4057: overflow in constant multiplication
  21772.     warning C4056: overflow in constant arithmetic
  21773.  
  21774.  The warnings occur as a side effect of the optimization of the second
  21775.  loop. Because the second loop has no functional value, it is optimized
  21776.  to the loop-terminating conditions by the compiler. The warnings
  21777.  appear to be benign; the program runs as expected. It is recommended,
  21778.  however, that if you encounter these errors you generate an assembly
  21779.  listing of the code and check the loop for correctness. These warnings
  21780.  do not occur in any version of QuickC, QCL, or QuickAssembler.
  21781.  
  21782.  Sample Code
  21783.  -----------
  21784.  
  21785.  #include<stdio.h>
  21786.  
  21787.  void main(void)
  21788.  {
  21789.       unsigned char *p1,
  21790.                        *start,
  21791.                        i,
  21792.                        j;
  21793.  
  21794.       start = "abcdefgh";
  21795.       for(i = 0, p1 = &start[7]; i < 7; i++){
  21796.            p1--;
  21797.            j = *p1;
  21798.       }
  21799.       for(i = 0, p1 = &start[7]; i < 7; i++){
  21800.            p1--;
  21801.       }
  21802.  }
  21803.  
  21804.  
  21805.  487. Calculating Available Memory in Large Model
  21806.  
  21807.  Product Version(s): 5.10
  21808.  Operating System:   MS-DOS
  21809.  Flags: ENDUSER | S_QuickC S_QuickAsm
  21810.  Last Modified: 17-JUL-1990    ArticleIdent: Q50297
  21811.  
  21812.  Question:
  21813.  
  21814.  I am using large-memory model (C Version 5.10). My program makes a
  21815.  call to the _memavl() function to see how much memory is remaining. I
  21816.  get back some number (for example, 29,320 bytes). Then I malloc some
  21817.  buffers for linked lists, data structures, and place another call to
  21818.  _memavl. I get back the same number.
  21819.  
  21820.  Shouldn't the number get smaller after I have malloc'd memory?
  21821.  
  21822.  Is there a way for me to find out how much free memory (total) is
  21823.  available?
  21824.  
  21825.  Response:
  21826.  
  21827.  There are two memory-allocation heaps when you're using large model.
  21828.  The near heap is the unused portion of the 64K DGROUP segment. The far
  21829.  heap is the unused memory above your program. malloc() uses the near
  21830.  heap for small and medium models and the far heap for compact, large,
  21831.  and huge models. [You can choose which heap to use by using _fmalloc()
  21832.  for the far heap and _nmalloc() for the near heap.]
  21833.  
  21834.  The _memavl() function measures only the amount of memory available on
  21835.  the near heap. Because the near heap is not used in far model until
  21836.  the far heap is exhausted, _memavl() does not necessarily change.
  21837.  
  21838.  To measure the amount of memory available on the far heap, you can use
  21839.  the _dos_allocmem() function. (This function calls the DOS
  21840.  memory-allocation function.) Pass the function 0xFFFF for the number
  21841.  of 16-byte paragraphs to allocate (which is 1 megabyte more memory
  21842.  than the machine has) and the address of an unsigned int. When the
  21843.  function returns, the unsigned int whose address you passed will
  21844.  contain the paragraph size of the largest contiguous block in the far
  21845.  heap. To find the number of bytes, multiply this by the 16L, which is
  21846.  the size of a paragraph. (Use 16L rather than 16 so that the
  21847.  multiplication will be done using long math, avoiding possible
  21848.  overflow.)
  21849.  
  21850.  The total memory available is the sum of the amount available on the
  21851.  far and near heaps. For best accuracy, you should do this calculation
  21852.  immediately after your program begins.
  21853.  
  21854.  The following are a few traits of the malloc() allocation family of
  21855.  which you should be aware:
  21856.  
  21857.  1. malloc() does NOT call DOS for each small allocation. Instead, it
  21858.     asks DOS for an 8K block (this size can be set by setting the
  21859.     global variable _amblksiz, as described on Page 33 of the
  21860.     "Microsoft C Run-Time Library Reference"), then allocate from this
  21861.     block. If the requested allocation is more than than 8K, malloc
  21862.     allocates enough 8K blocks to fulfill the allocation. Before
  21863.     malloc() asks DOS for memory, it first tries to allocate the
  21864.     request from memory it already has.
  21865.  
  21866.  2. free() NEVER returns memory to DOS. So, if you allocated a block,
  21867.     checked the far heap space using _dos_allocmem(), free()'d the
  21868.     block and checked again, the amount of memory available to DOS
  21869.     would NOT increase on the second call. You can get a better idea of
  21870.     how much memory is available by using _heapwalk() to find out how
  21871.     much memory is available to malloc() but not to DOS.
  21872.  
  21873.  Note: halloc() calls DOS directly and frees directly [using hfree()]
  21874.  back to DOS.
  21875.  
  21876.  A program that calculates an estimate of the total amount of free
  21877.  memory follows:
  21878.  
  21879.  Sample Program
  21880.  --------------
  21881.  
  21882.  #include <malloc.h>
  21883.  #include <dos.h>
  21884.  #include <stdio.h>
  21885.  
  21886.  void main(void)
  21887.  {
  21888.  long farheap = 0, total_free, available;
  21889.  unsigned farparaavail;
  21890.  struct _heapinfo hinfo;
  21891.  int heapstatus;
  21892.  
  21893.    /* Calculates the total memory available in the far heap       */
  21894.  
  21895.    hinfo._pentry = NULL;
  21896.    while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
  21897.           if (!hinfo._useflag)
  21898.                  farheap += hinfo._size;
  21899.  
  21900.    /* _dos_allocmem will return the maximum block size available */
  21901.    /* _memavl() will return the maximum memory in the near heap  */
  21902.  
  21903.    _dos_allocmem(0xFFFF, &farparaavail);
  21904.    available = (long)farparaavail * 16L + _memavl();
  21905.  
  21906.    /* Total memory available for allocation */
  21907.  
  21908.    total_free = farheap + available;
  21909.    printf("Total memory available is about %ld bytes\n", total_free);
  21910.  }
  21911.  
  21912.  The total memory calculated in the far heap may not be in a contiguous
  21913.  block. To see whether or not memory has been fragmented, add the
  21914.  following line to the while loop:
  21915.  
  21916.     printf ("%6s block at %p of size %4.4X\n,
  21917.     (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
  21918.     hinfo._pentry, hinfo._size);
  21919.  
  21920.  To see how fragmented the near heap is, change the _heapwalk() in the
  21921.  while statement to _nheapwalk(). This forces the function to do a heap
  21922.  walk on the near heap. The _heapwalk() defaults to the following:
  21923.  
  21924.     _fheapwalk in Compact and Large model
  21925.     _nheapwalk in Medium and Small model
  21926.  
  21927.  
  21928.  488. atexit() Returns Zero if Successful
  21929.  
  21930.  Product Version(s): 5.00 5.10
  21931.  Operating System:   MS-DOS
  21932.  Flags: ENDUSER| | docerr S_QuickC
  21933.  Last Modified: 30-NOV-1989    ArticleIdent: Q50334
  21934.  
  21935.  Question:
  21936.  
  21937.  The "Microsoft C for the MS-DOS Operating System: Run-Time Library
  21938.  Reference" has conflicting statements regarding the return code from
  21939.  atexit(). What is the proper return code?
  21940.  
  21941.  Response:
  21942.  
  21943.  There is an error in the run-time library reference for the atexit()
  21944.  function (Page 124) under DESCRIPTION. The correct return values are
  21945.  described in the RETURN VALUE section. atexit() should return a value
  21946.  of zero (0) if successful and nonzero (-1) on error.
  21947.  
  21948.  
  21949.  489. Passing a Stream File Pointer (FILE *) Between DLLs
  21950.  
  21951.  Product Version(s): 5.10
  21952.  Operating System:   OS/2
  21953.  Flags: ENDUSER |
  21954.  Last Modified: 17-JUL-1990    ArticleIdent: Q50336
  21955.  
  21956.  Question:
  21957.  
  21958.  Regarding single-thread DLLs built with the C 5.10 single-thread
  21959.  DLL support library LLIBCDLL.LIB:
  21960.  
  21961.  My main() function calls a function in my first DLL, which fopen()s a
  21962.  buffered stream file. The function in my first DLL calls a function
  21963.  in my second DLL, passing the stream pointer (FILE *) as an argument.
  21964.  When the function in my second DLL attempts to fread() the stream for
  21965.  the first time (which causes the allocation of the stream buffer), a
  21966.  General Protect fault (segment violation Trap 13 or 0xD) occurs. What
  21967.  went wrong, and how can I work around the problem?
  21968.  
  21969.  Response:
  21970.  
  21971.  This procedure cannot be done with LLIBCDLL-created DLLs because the
  21972.  second DLL has no way to know where the internal C run-time library
  21973.  data structures are, which in this case would be the data structures
  21974.  for the file stream that was opened in the first DLL.
  21975.  
  21976.  To share file streams between DLLs or between an .EXE and DLLs, use
  21977.  the dynamically linked, multithread support C run-time function
  21978.  CRTLIB.DLL. The correct way to do this is to have one of your DLLs
  21979.  export a version of the fread() function and/or fopen() function. The
  21980.  fopen() and fread() that get called must be in the same DLL.
  21981.  
  21982.  
  21983.  490. Internal Compiler Error: ctypes.c:1.107, Line 474
  21984.  
  21985.  Product Version(s): 5.10   | 5.10
  21986.  Operating System:   MS-DOS | OS/2
  21987.  Flags: ENDUSER |
  21988.  Last Modified: 30-NOV-1989    ArticleIdent: Q50337
  21989.  
  21990.  The program below generates the following error when compiled with the
  21991.  default command-line options under the Microsoft C optimizing compiler
  21992.  Version 5.10:
  21993.  
  21994.     intr.c(12) : fatal error C1001: Internal Compiler Error
  21995.                     (compiler file '@(#)ctypes.c:1.107', line 474)
  21996.                     Contact Microsoft Technical Support
  21997.  
  21998.  The following program demonstrates the internal compiler error:
  21999.  
  22000.  #define  interrupt_number = 0x62     /*  any number will do */
  22001.  
  22002.  struct interface {
  22003.                       int counter;
  22004.                       char signature[8];
  22005.                   } far interface;
  22006.  
  22007.  void far*far*interrupt_vector = ( void far * )0L;
  22008.  
  22009.  int main( void )
  22010.  {
  22011.     /* offending line--invalid */
  22012.     interrupt_vector[interrupt_number] = interface;
  22013.  
  22014.     /* replace with this line */
  22015.  // interrupt_vector[interrupt_number] = &interface;
  22016.  }
  22017.  
  22018.  The program is not syntactically valid: the offending line attempts to
  22019.  assign a structure (rather than a pointer to the structure) to a void
  22020.  function pointer.
  22021.  
  22022.  Modifying the offending line of code to a pointer rather than a
  22023.  structure [i.e., using the "address of" operator ("&") on the
  22024.  interface structure] eliminates the internal compiler error and makes
  22025.  the program correct.
  22026.  
  22027.  
  22028.  491. C and Pascal Mixed Language: Declare C Libraries First
  22029.  
  22030.  Product Version(s): 5.10   | 5.10
  22031.  Operating System:   MS-DOS | OS/2
  22032.  Flags: ENDUSER | S_PASCAL S_LINK
  22033.  Last Modified: 30-NOV-1989    ArticleIdent: Q50703
  22034.  
  22035.  When doing mixed language programming with C Version 5.10 and Pascal
  22036.  Version 4.00, be sure to use the /NOD and /NOE linker switches, and
  22037.  then specifically link with the C libraries before the Pascal
  22038.  libraries. This will prevent the linker from finding multiply defined
  22039.  symbols.
  22040.  
  22041.  The linker will often report error L2025 when linking with the Pascal
  22042.  library first, depending on what functions are called from C. The
  22043.  printf() function is one example of a run-time function that will
  22044.  cause this problem. The problem occurs because some of the low-level
  22045.  routines involved in both libraries have the same name.
  22046.  
  22047.  The following example typifies the problems encountered:
  22048.  
  22049.  For instance, say that the Pascal library contains an object module
  22050.  with a routine called A, and the C library contains an object module
  22051.  with routine A as well as routine B.
  22052.  
  22053.  Furthermore, suppose the Pascal code makes a call to the A library
  22054.  routine and the C code makes a call to the B library routine.
  22055.  
  22056.  If the Pascal libraries are linked first, the A .OBJ will be found in
  22057.  the Pascal library, then the A and B .OBJ will be brought in from the
  22058.  C library to resolve the call to B. This results in the linker
  22059.  receiving two copies of routine A, which causes the error. By linking
  22060.  the C library first, only the one object module (with both A and B)
  22061.  will be found, and the symbol will not be multiply defined.
  22062.  
  22063.  
  22064.  492. Preprocessor Condenses Multi-Line Macro Invocations
  22065.  
  22066.  Product Version(s): 5.00 5.10 | 5.10
  22067.  Operating System:   MS-DOS    | OS/2
  22068.  Flags: ENDUSER |
  22069.  Last Modified: 17-JUL-1990    ArticleIdent: Q50341
  22070.  
  22071.  The preprocessor of the Microsoft C Optimizing Compiler versions 5.00
  22072.  and 5.10 does not preserve the source code structure of macro
  22073.  invocations upon expansion. Preprocessor macro expansion is carried
  22074.  out on one line at a time, in a left to right fashion, until the
  22075.  end-of-line is reached. Thus, when multiple-line macro invocations are
  22076.  expanded, they are converted into a single line of code.
  22077.  
  22078.  The following example defines a simple macro and displays this
  22079.  conversion of multi-line macro invocations:
  22080.  
  22081.  #define macro( arg1, arg2, arg3 ) arg1 + arg2 + arg3
  22082.  
  22083.       Source Code           Preprocessor Listing
  22084.      _____________          ____________________
  22085.  
  22086.    value = macro ( param1,  value = macro( param1 + param2 + param3 );
  22087.                    param2,
  22088.                    param3 );
  22089.  
  22090.  Note that the preprocessor listing replaces the three lines of code
  22091.  in the source file with only one line. As a result, the line numbers
  22092.  between the two files are different because the preprocessor does not
  22093.  perform any line number adjustment.
  22094.  
  22095.  This may cause problems if one must compile preprocessor listings to
  22096.  avoid errors generated by .C source files (i.e., insufficient heap
  22097.  space). When the preprocessor listing is compiled, the subtle side
  22098.  effect becomes more obvious in the form of discrepancies between
  22099.  original source-code line numbers and line numbers associated with
  22100.  compiler errors or debugger maps. This result can make debugging
  22101.  original source code difficult and can be a general nuisance when
  22102.  trying to locate erroneous lines in source code indicated by the
  22103.  compiler.
  22104.  
  22105.  The #line directive and the __LINE__ predefined macro can be used to
  22106.  redefine preprocessor listing line numbers and eliminate such
  22107.  differences. To compensate for the preprocessor single-line expansion
  22108.  of macro invocations, place the directive "#line __LINE__" in the
  22109.  source code line following the macro invocation.
  22110.  
  22111.  The #line directive, which accepts an integer constant as an argument,
  22112.  instructs the preprocessor to change the compiler's internally stored
  22113.  line number to the integer argument specified. The __LINE__ macro,
  22114.  which is supplied as the argument to the #line directive, evaluates to
  22115.  the current line number generated during preprocessing. Working
  22116.  together, they force the compiler to generate consistent line numbers
  22117.  between the the source file and the preprocessor listing.
  22118.  
  22119.  The program below illustrates the macro expansion behavior of the C
  22120.  preprocessor and how it can be modified to generate
  22121.  line-number-compatible source and preprocessor listings.
  22122.  
  22123.            /* TEST.C */           |          /* TEST.I */
  22124.                                   |
  22125.  /*1*/  #define sum( a,b,c) a+b+c | /*1*/  #define sum(a,b,c) a+b+c
  22126.  /*2*/                            | /*2*/
  22127.  /*3*/  void main( void )         | /*3*/    void main( void )
  22128.  /*4*/  {                         | /*4*/    {
  22129.  /*5*/     int i;                 | /*5*/   int i;
  22130.  /*6*/     i =  sum( 1,           | /*6*/   i =  sum( 1, 2, 3 );
  22131.  /*7*/           2,               | /*7*/   /*  #line __LINE__    */
  22132.  /*8*/           3 );             | /*8*/   i = 100000;
  22133.  /*9*/     /*  #line __LINE__  */ | /*9*/    }
  22134.  /*10*/    i = 100000;            | /*10*/
  22135.  /*11*/ }                         | /*11*/
  22136.                                   |
  22137.  
  22138.  When the program, TEST.C, above is compiled under warning level three,
  22139.  a data conversion warning is generated for line 10, indicating
  22140.  overflow of the integer variable i. TEST.C is then run through the
  22141.  preprocessor using the /P compiler option, where TEST.I (above) is
  22142.  generated. Compiling TEST.I under warning level three generates the
  22143.  same data conversion warning, but on line 8. The line number
  22144.  difference between TEST.C and TEST.I is quite obvious.
  22145.  
  22146.  By uncommenting line 9 in the TEST.C, both the source file and
  22147.  preprocessor listing contain consistent line numbers following the
  22148.  macro invocation because the line number is reset to the proper value
  22149.  (seven) after the preprocessor pass.
  22150.  
  22151.  
  22152.  493. mktemp() Creates a Maximum of 27 Unique Filenames
  22153.  
  22154.  Product Version(s): 5.10   | 5.10
  22155.  Operating System:   MS-DOS | OS/2
  22156.  Flags: ENDUSER | S_QuickC docerr
  22157.  Last Modified: 30-NOV-1989    ArticleIdent: Q50351
  22158.  
  22159.  It is unclear in the documentation for the mktemp() function in the
  22160.  Version 5.10 "Microsoft C Optimizing Compiler for the MS-DOS Operating
  22161.  System Run-Time Library Reference" (Page 432) exactly how many
  22162.  filenames mktemp() creates. The reference states the following:
  22163.  
  22164.     When creating new names, mktemp uses, in order, "0" and the
  22165.     lowercase letters "a" to "z".
  22166.  
  22167.  This is correct; however, the documentation fails to mention that
  22168.  these are the only filenames that are created. Any further calls to
  22169.  mktemp (after "z" has already been placed in the template) fail.
  22170.  Therefore, this limits the number of unique filenames to 27.
  22171.  
  22172.  
  22173.  494. Compiling isatty() Sample Program Gives C2146: Syntax Error
  22174.  
  22175.  Product Version(s): 5.00 5.10 | 5.00 5.10
  22176.  Operating System:   MS-DOS    | OS/2
  22177.  Flags: ENDUSER | DOCERR
  22178.  Last Modified: 30-NOV-1989    ArticleIdent: Q50704
  22179.  
  22180.  On Page 376 of the "Microsoft C Run-Time Library Reference" for C
  22181.  Versions 5.00 and 5.10, the sample program for the function isatty()
  22182.  will generate a syntax error when compiled. The zero in the printf()
  22183.  statement should be changed to a double quotation mark (i.e., %s0
  22184.  should be %s"). The following is the printf() statement with the
  22185.  correct syntax:
  22186.  
  22187.     printf ("Is stdout redirected? %s", interactive ? "no" : "yes");
  22188.  
  22189.  
  22190.  495. Run-Time Routines Assume That Direction Flag Is Clear in C
  22191.  
  22192.  Product Version(s): 5.10   | 5.10
  22193.  Operating System:   MS-DOS | OS/2
  22194.  Flags: ENDUSER | DOCERR S_QUICKC S_QUICKASM
  22195.  Last Modified: 30-NOV-1989    ArticleIdent: Q50712
  22196.  
  22197.  The C run-time routines assume that the direction flag is cleared. If
  22198.  you are using other functions with the C run-time functions, you must
  22199.  ensure that the other functions leave the direction flag alone or
  22200.  restore it to its original condition. Expecting the direction flag to
  22201.  be clear upon entry makes the run-time code faster and more efficient.
  22202.  
  22203.  The run-time functions that use the direction flag include the string
  22204.  manipulation and buffer manipulation routines.
  22205.  
  22206.  This is documented on Page 365 of the "Microsoft Macro Assembler
  22207.  Programmer's Guide," Versions 5.00 and 5.10:
  22208.  
  22209.     Under DOS, the direction flag will normally be cleared
  22210.     if your program has not changed it.
  22211.  
  22212.  This information is not included in the C 5.10 or QuickC 2.00 or 2.01
  22213.  manuals.
  22214.  
  22215.  
  22216.  496. R6009 Not Enough Space for Environment -- Possible Workarounds
  22217.  
  22218.  Product Version(s): 5.10
  22219.  Operating System:   MS-DOS
  22220.  Flags: ENDUSER | s_quickasm s_quickc
  22221.  Last Modified: 21-FEB-1990    ArticleIdent: Q50714
  22222.  
  22223.  The "Not Enough Space For Environment" error is caused when a program
  22224.  successfully loads into memory and then attempts to load a copy of the
  22225.  environment and the argument list into the near heap. If the near heap
  22226.  does not have enough room for one or the other, or both, R6009 is
  22227.  generated.
  22228.  
  22229.  In standard Microsoft C programs, the functions _setargv and _setenvp
  22230.  attempt to set up the argument vector and the environment vector,
  22231.  respectively. Both of these vectors are allocated in the near heap. If
  22232.  the program has a full or nearly full near heap, the vectors will not
  22233.  be set up, thereby giving the error.
  22234.  
  22235.  A few ways to get around the problem are as follows:
  22236.  
  22237.  1. Lower the amount of environment space, with the following statement
  22238.     in the CONFIG.SYS file. This assumes that environment space is
  22239.     being allocated.
  22240.  
  22241.        shell=command.com /p /e:xxxx
  22242.  
  22243.  2. Use the large memory model when compiling in conjunction with the
  22244.     /Gt switch to get some of the global data out of DGROUP, thus
  22245.     freeing up room for the environment and/or the argument list.
  22246.  
  22247.  3. If there is no need for command line arguments, _setargv can be
  22248.     rewritten as follows:
  22249.  
  22250.        _setargv() {}
  22251.  
  22252.  4. If there is no need for a copy of the environment, and if the
  22253.     spawn or exec function is not needed, _setenvp can be rewritten
  22254.     as follows:
  22255.  
  22256.        _setenvp() {}
  22257.  
  22258.  For more information on workarounds 3 and 4, see Section 5.2.2,
  22259.  "Suppressing Command Line Processing," in the C user's guide.
  22260.  
  22261.  
  22262.  497. No Compiler Errors Produced When Assigning to Missing struct
  22263.  
  22264.  Product Version(s): 5.10   | 5.10
  22265.  Operating System:   MS-DOS | OS/2
  22266.  Flags: ENDUSER |
  22267.  Last Modified: 30-NOV-1989    ArticleIdent: Q50732
  22268.  
  22269.  Code that assigns a value to a nonexistent structure compiles without
  22270.  warning or error in Microsoft C 5.10 and QuickC Versions 2.00 and
  22271.  2.01. This is correct behavior.
  22272.  
  22273.  Note that dereferencing a pointer to an undefined structure, or
  22274.  attempting to use a field will produce errors. In general, you are
  22275.  allowed to make a reference to an undefined struct as long as the
  22276.  operation doesn't have to know the size of that struct or the names of
  22277.  its fields. This method of declaration is commonly used in linked
  22278.  lists.
  22279.  
  22280.  void main (void)
  22281.  {
  22282.     struct non_existant *ptr;             // legal
  22283.     struct x{
  22284.              struct x *previous;          // legal, note that struct x is
  22285.              struct x *next;              // not yet defined
  22286.             }
  22287.                  .
  22288.                  .
  22289.                  .
  22290.                  .
  22291.  }
  22292.  
  22293.  
  22294.  498. Huge Indirection May not Cross Segment Boundaries
  22295.  
  22296.  Product Version(s): 5.10   | 5.10
  22297.  Operating System:   MS-DOS | OS/2
  22298.  Flags: ENDUSER | S_QuickC
  22299.  Last Modified: 30-NOV-1989    ArticleIdent: Q50733
  22300.  
  22301.  Microsoft C will never generate an array element that spans a segment
  22302.  boundary. If a customer generates a scenario where this situation
  22303.  occurs, Microsoft C will generate incorrect addresses for the element
  22304.  that crosses the segment boundary. Placing elements such that they
  22305.  could cross a segment boundary is an incorrect coding technique, not a
  22306.  problem with Microsoft C and huge pointer addressing.
  22307.  
  22308.  For instance, if a huge character buffer has been allocated and
  22309.  structure data has been copied to this buffer, it is possible to
  22310.  access this data in structure format by first setting a huge pointer
  22311.  to the address of the structure you want and then specifying the huge
  22312.  pointer followed by the structure pointer operator (->) and the name
  22313.  of element you want to access.
  22314.  
  22315.  However, if the structure you are looking at crosses a segment
  22316.  boundary, then the indirection will fail. If the element of the
  22317.  structure you are referencing is in another segment, your pointer will
  22318.  usually end up offsetting by the correct number of bytes, but in the
  22319.  current segment and not the next segment.
  22320.  
  22321.  Code Example
  22322.  ------------
  22323.  
  22324.  char huge buffer[70000];                /* Any huge buffer larger than 64K */
  22325.  struct x { int x,y,z; };                /* Any structure */
  22326.  
  22327.  /* Assume that buffer has been filled with many structures of type x.
  22328.     Since the structures were put into the buffer via byte copy, it
  22329.     is very likely that one of the structures will cross over the segment
  22330.     boundary. */
  22331.  
  22332.  struct x huge *test_ptr;                /* A huge pointer to x */
  22333.  
  22334.  test_ptr = (struct x huge *)(buffer+( 65536 - sizeof(struct x) ) );
  22335.  
  22336.  /* test_ptr is now equal to some offset into huge character buffer.
  22337.     It is assumed that the user has given test_ptr a legitimate address
  22338.     of a structure that is contained in the buffer in an attempt to access
  22339.     that structure. */
  22340.  
  22341.  test_ptr->z = 5;
  22342.  
  22343.  /* The line above will create an incorrect address for the element z if
  22344.     z is in a segment other than the one specified by the huge pointer.
  22345.     This address will probably end up as the correct offset but in the
  22346.     same segment because, although the pointer is huge, it still will not
  22347.     compute the segment when used with indirection. This is also why
  22348.     huge structure arrays are padded and why huge arrays larger than
  22349.     128K must have elements whose size is a power of two. */
  22350.  
  22351.  Note: This problem can avoided by simply creating a huge array of
  22352.  structures instead of characters. The compiler will take care of
  22353.  padding the array so that an array element (a structure) will not
  22354.  cross a segment boundary.
  22355.  
  22356.  This would seem to be a bug in the compiler since the huge pointer
  22357.  cannot access data beyond a segment boundary. The situation where an
  22358.  array element crosses a segment boundary would never be generated by
  22359.  Microsoft C, however. Accordingly, the huge pointer arithmetic does
  22360.  not account for such a situation. This is not a bug in the compiler,
  22361.  but an error in the code.
  22362.  
  22363.  
  22364.  499. Graphics Mode: Getting More Than One Background Color
  22365.  
  22366.  Product Version(s): 5.10
  22367.  Operating System:   MS-DOS
  22368.  Flags: ENDUSER| | S_QuickC S_QuickASM
  22369.  Last Modified: 17-JUL-1990    ArticleIdent: Q50411
  22370.  It is not possible to display more than one background color on the
  22371.  screen when working in graphics mode. However, it is possible to
  22372.  present the illusion of creating different background colors for
  22373.  various windows overlaid on top of the current background color. Use
  22374.  _rectangle and _floodfill to create the windows, and either _outtext
  22375.  or _outgtext to output the text. A common application is the creation
  22376.  of a screen similar to the following:
  22377.  
  22378.  |-----------------------------------------------------------------|
  22379.  |                                                                 |
  22380.  |                                   Light Blue Background         |
  22381.  |                                                                 |
  22382.  |                |------------------------|                       |
  22383.  |                |                        |                       |
  22384.  |                |    Dark Blue           |                       |
  22385.  |                |    Background          |                       |
  22386.  |                |                        |                       |
  22387.  |                |------------------------|                       |
  22388.  |                                                                 |
  22389.  |                                                                 |
  22390.  |-----------------------------------------------------------------|
  22391.  
  22392.  This is not difficult. The primary problem is getting around the fact
  22393.  that, when using _outtext, the text always outputs on blocks of the
  22394.  current background color. The result of this is that inside of your
  22395.  dark blue window, you will have text surrounded by borders of light
  22396.  blue (not very attractive!). To work around this, you can rely on the
  22397.  fact that _floodfill() uses the foreground color as its boundary, and
  22398.  not the background color. Therefore, you can set the background and
  22399.  foreground color equal to the color of the inner window (Dark Blue
  22400.  above), and draw a rectangle with _GFILLINTERIOR to the size of the
  22401.  window you desire. Then, change the foreground color with _setcolor().
  22402.  Next, you can use _floodfill() from point (0,0) with the boundary
  22403.  color set to the same color index as the rectangle. After this, you
  22404.  can use _settextcolor() and _outtext to put text in the inner window
  22405.  without problem. An sample program, WINDOW.C, can be found in the
  22406.  "More Information:" section of this article.
  22407.  
  22408.  An easier alternative is to use QuickC's fonts. _outgtext does not
  22409.  reset the character background to the current background color.
  22410.  Instead, it draws the character over any existing images already on
  22411.  the screen. Therefore, all that is necessary is to create a filled
  22412.  rectangle of the desired size, register and set the desired font, and
  22413.  output text to that area of the screen by using _outgtext. An sample
  22414.  program, FONTS.C, can be found in the "More Information:" section of
  22415.  this article.
  22416.  
  22417.  -----------------------------------------------------------------------
  22418.  /* WINDOW.C: A sample program that illustrates changing the          */
  22419.  /* color for a window using _outtext, _floodfill, and _rectangle.    */
  22420.  
  22421.  #include <graph.h>                     /* for the graphics functions */
  22422.  #include <conio.h>                     /* for getch()                */
  22423.  
  22424.  void main(void)
  22425.  {
  22426.  _setvideomode(_ERESCOLOR);              /* set to graphics mode      */
  22427.  _setbkcolor(_BLUE);                     /* change background color   */
  22428.  _setcolor(1);                           /* set drawing color         */
  22429.  _settextcolor(3);                       /* set text color            */
  22430.  _rectangle(_GFILLINTERIOR,100,100,540,250); /* draw a window         */
  22431.  _setcolor(9);                           /* change color for fill     */
  22432.  _floodfill(0, 0, 1);                    /* fill in the background    */
  22433.  _settextposition(12, 35);               /* coordinates inside square */
  22434.  _outtext("scribble");                   /* output text inside square */
  22435.  getch();                                /* wait for a key hit        */
  22436.  _setvideomode(_DEFAULTMODE);            /* reset the video mode      */
  22437.  }
  22438.  
  22439.  /*--------------------------------------------------------------------*/
  22440.  /* FONTS.C : a slight modification to the "fonts.c" program from the  */
  22441.  /* QuickC 2.00 online help system, which outputs the fonted text onto */
  22442.  /* a "window" of a different color, easily producing the effect of    */
  22443.  /* a secondary, window-area-only background color.                    */
  22444.  
  22445.  #include <conio.h>
  22446.  #include <stdio.h>
  22447.  #include <stdlib.h>
  22448.  #include <string.h>
  22449.  #include <graph.h>
  22450.  
  22451.  #define NFONTS 6
  22452.  
  22453.  unsigned char *face[NFONTS] =
  22454.  {
  22455.      "Courier", "Helvetica", "Times Roman", "Modern", "Script", "Roman"
  22456.  };
  22457.  unsigned char *options[NFONTS] =
  22458.  {
  22459.       "courier", "helv", "tms rmn", "modern", "script", "roman"
  22460.  };
  22461.  
  22462.  main ()
  22463.  {
  22464.            unsigned char list[20];
  22465.            char fondir[_MAX_PATH]="d:\qc2\bin";  /* modify path!!!!!   */
  22466.            struct videoconfig vc;
  22467.            struct _fontinfo fi;
  22468.            short fontnum, x, y, mode = _VRES16COLOR;
  22469.  
  22470.            /* Read header info from all .FON files in given directory. */
  22471.            if( _registerfonts( fondir ) <= 0 )
  22472.            {
  22473.            _outtext( "Error: can't register fonts" );
  22474.            exit( 1 );
  22475.            }
  22476.  
  22477.       /* Set highest available graphics mode and get configuration. */
  22478.       while( !_setvideomode( mode ) )
  22479.         mode--;
  22480.         if( mode == _TEXTMONO)
  22481.           exit( 1 );
  22482.           _getvideoconfig( &vc );
  22483.  
  22484.       /* Display each font name centered on screen. */
  22485.       for( fontnum = 0; fontnum < NFONTS; fontnum++ )
  22486.           {
  22487.       /* Build options string. */
  22488.       strcat( strcat( strcpy( list, "t'" ), options[fontnum] ), "'");
  22489.       strcat( list, "h30w24b" );
  22490.  
  22491.       _clearscreen( _GCLEARSCREEN );
  22492.       if( !_setfont( list ) )
  22493.       {
  22494.       /* Use length of text and height of font to center text. */
  22495.       x = (vc.numxpixels / 2) - (_getgtextextent( face[fontnum] ) / 2);
  22496.         if( _getfontinfo( &fi ) )
  22497.           {
  22498.             _outtext( "Error: Can't get font information" );
  22499.             break;
  22500.            }
  22501.       y = (vc.numypixels / 2) - (fi.ascent / 2);
  22502.       _moveto( x, y );
  22503.         if( vc.numcolors > 2 )
  22504.        /* set up the background window & fill before text output   */
  22505.          _setcolor( fontnum + 2);            /* set window color   */
  22506.          _rectangle(_GFILLINTERIOR,100, 100, 540, 250);
  22507.          _setcolor(fontnum+1);               /* set color for text */
  22508.          _outgtext( face[fontnum] );         /* output fonted text */
  22509.          getch();
  22510.          }
  22511.          else
  22512.          _outtext( "Error: Can't set font" );
  22513.          }
  22514.          _unregisterfonts();           /* free up memory used by fonts*/
  22515.          exit( !_setvideomode( _DEFAULTMODE ) );
  22516.  }
  22517.  
  22518.  
  22519.  500. With /CP:1, _memavl() Still Shows Memory Available
  22520.  
  22521.  Product Version(s): 5.10   | 5.10
  22522.  Operating System:   MS-DOS | OS/2
  22523.  Flags: ENDUSER | S_QuickC S_LINK
  22524.  Last Modified: 30-NOV-1989    ArticleIdent: Q50472
  22525.  
  22526.  Using the /CP:1 (/CPARMAXALLOC - set maximum memory allocation) link
  22527.  option does not always leave 1 byte available for allocation in the
  22528.  near heap allocation. This becomes apparent when making a call to
  22529.  _memavl().
  22530.  
  22531.  Code Example
  22532.  ------------
  22533.  
  22534.  /* test.c */
  22535.  
  22536.  #include <malloc.h>
  22537.  #include <stdio.h>
  22538.  
  22539.  void main(void)
  22540.  {
  22541.       /* _amblksiz=1; */
  22542.       /* The above line uncommented will cause only a couple
  22543.          bytes to become available (see More Information:). */
  22544.       printf("Available memory in near heap = %d\n",
  22545.              _memavl());
  22546.  }
  22547.  
  22548.  /* The following options were used to create the program:
  22549.  
  22550.     cl /c test.c
  22551.     link /CP:1 test
  22552.  
  22553.     This program will show approximately 4K available when
  22554.  executed. */
  22555.  
  22556.  What happens is that _memavl() itself is causing the near heap to
  22557.  grow. The library functions _memavl, _freect, and _memmax all require
  22558.  the heap to be initialized for them to work. If the heap is not
  22559.  initialized then a malloc(0) call is made. The malloc call causes
  22560.  DGROUP to grow to the next _amblksiz boundary (8K by default). This
  22561.  usually does not cause a problem because malloc is usually called
  22562.  either before or after the _memavl.
  22563.  
  22564.  To reduce the amount of memory taken by DGROUP initialization, set
  22565.  _amblksiz to some smaller amount in order for malloc(0) to grab only
  22566.  as much it absolutely needs.
  22567.  
  22568.  
  22569.  501. GRAPHICS.LIB Not Supported in C for OS/2
  22570.  
  22571.  Product Version(s): 5.10   | 5.10
  22572.  Operating System:   MS-DOS | OS/2
  22573.  Flags: ENDUSER | S_QuickC S_QuickASM
  22574.  Last Modified: 30-NOV-1989    ArticleIdent: Q50474
  22575.  
  22576.  GRAPHICS.LIB is a real-mode library and its use in a protected mode
  22577.  application leads to a general protection fault or a protection
  22578.  violation.
  22579.  
  22580.  
  22581.  502. BX Register Is Popped Twice for a C Interrupt Function
  22582.  
  22583.  Product Version(s): 5.10   | 5.10
  22584.  Operating System:   MS-DOS | OS/2
  22585.  Flags: ENDUSER | S_QuickC S_QuickAsm 2.00 2.01
  22586.  Last Modified: 21-MAR-1990    ArticleIdent: Q50518
  22587.  
  22588.  The interrupt keyword is used to designate specific C functions as
  22589.  interrupt service routines and instructs the compiler to generate
  22590.  appropriate entry and exit instructions.
  22591.  
  22592.  If you compile code with the /G1 or /G2 options (80186 or 80286 code
  22593.  generation) then the compiler produces pusha and popa instructions
  22594.  that save and restore all vital registers.
  22595.  
  22596.  However, if you compile with the default /G0 (8086 code generation)
  22597.  then the registers are each explicitly pushed and popped. One
  22598.  difference in this code, which may at first appear to be a bug, is
  22599.  that the BX register is popped twice, but the SP register is not
  22600.  popped at all.
  22601.  
  22602.  This is not a problem. The SP register is saved in the following
  22603.  instruction sequence:
  22604.  
  22605.     mov     bp, sp
  22606.     .
  22607.     .       ISR code
  22608.     .
  22609.     mov     sp, bp
  22610.  
  22611.  The peculiar double popping of BX can be explained by the following:
  22612.  
  22613.     The registers are pushed AX, CX, DX, BX, SP, BP, SI, DI, DS, ES
  22614.     (left to right)
  22615.  
  22616.     The registers are popped AX, CX, DX, BX, BX, BP, SI, DI, DS, ES
  22617.     (right to left)
  22618.  
  22619.  Notice that ES receives the old ES; DS the old DS, but BX receives the
  22620.  old SP, then BX receives the old BX.
  22621.  
  22622.  The first pop of SP to BX is necessary to remove the previous value of
  22623.  SP from the stack. The second pop of BX is necessary to restore the
  22624.  old BX value.
  22625.  
  22626.  The old value of SP was restored in the "MOV  SP,BP" instruction,
  22627.  which immediately proceeds the popping of all the registers.
  22628.  
  22629.  This ensures that the state of the registers are saved and then
  22630.  restored in the Interrupt Service Routine.
  22631.  
  22632.  
  22633.  503. Loader Uses Return Value from a DLL's Initialization Routine
  22634.  
  22635.  Product Version(s): 5.10
  22636.  Operating System:   OS/2
  22637.  Flags: ENDUSER |
  22638.  Last Modified: 21-MAR-1990    ArticleIdent: Q50519
  22639.  
  22640.  Question:
  22641.  
  22642.  How is the return value from a DLL's initialization routine used?
  22643.  
  22644.  Response:
  22645.  
  22646.  The return value from a DLL's initialization is used by the loader.
  22647.  
  22648.  Using an initialization routine for your DLL is optional. The
  22649.  initialization routine can be global or instance. The initialization
  22650.  routine is called when the DLL is loaded. [This is not necessarily the
  22651.  same time as when a DLL-exported function is called. For example, if
  22652.  you load the DLL using DosLoadModule() and DosGetProcAddr(), the
  22653.  initialization routine is run and the return value is examined at that
  22654.  time.]
  22655.  
  22656.  Every time you run a program that uses DLLs, the loader goes through
  22657.  the import list in the exehdr and attempts to load all the DLLs. As it
  22658.  tries to load each DLL, it runs its initialization routine (depending
  22659.  on whether the init routine is instance or global). If the
  22660.  initialization routine fails (even if the DLL is found) the system may
  22661.  display a message, or simply terminate at that point.
  22662.  
  22663.  Initialization routines are mentioned in Ray Duncan's book, "Advanced
  22664.  OS/2 Programming," in Chapter 19, "Dynamic Link Libraries," Pages
  22665.  459-469.
  22666.  
  22667.  
  22668.  504. Floating-Point Initialization Occurs at Link Time
  22669.  
  22670.  Product Version(s): 5.10   | 5.10
  22671.  Operating System:   MS-DOS | OS/2
  22672.  Flags: ENDUSER | S_QuickC S_QuickASM
  22673.  Last Modified: 21-MAR-1990    ArticleIdent: Q50523
  22674.  
  22675.  Floating-point initialization occurs at link time. If the compiler has
  22676.  generated any floating-point instructions, it lists an external
  22677.  symbol. When the linker sees the external symbol, it brings in the
  22678.  necessary segment.
  22679.  
  22680.  In C 5.10, the external symbol is __fltused. The linker brings in a
  22681.  module that has a common CDATA segment that defines the correct values
  22682.  of fpmath, fpdata, and fpsignal. If this module is not brought in, the
  22683.  CDATA segment defaults to all zeros. This is why CDATA is defined as
  22684.  common and not public.
  22685.  
  22686.  This process causes the floating-point support to be linked only if
  22687.  floating point is used.
  22688.  
  22689.  
  22690.  505. C Run-Time Routines Cannot Be Placed in an Overlay
  22691.  
  22692.  Product Version(s): 5.10
  22693.  Operating System:   MS-DOS
  22694.  Flags: ENDUSER | S_QuickC S_QuickASM
  22695.  Last Modified: 30-NOV-1989    ArticleIdent: Q50524
  22696.  
  22697.  Problem:
  22698.  
  22699.  I want to extract a routine from the C Run-Time Library and put it in
  22700.  an overlay. The program compiles and links without warnings or errors,
  22701.  but when I run the program, my machine hangs.
  22702.  
  22703.  Response:
  22704.  
  22705.  The run-time routines for medium and large models (the only ones that
  22706.  overlays deal with) are compiled with /NT _TEXT. This puts all the
  22707.  routines in the same named segment. The linker cannot split a segment
  22708.  between the root and overlay. Segmentation takes precedence over
  22709.  overlays. The linker constructs overlays from segments, not individual
  22710.  functions.
  22711.  
  22712.  The first request for the segment (in an .OBJ that goes in root or in
  22713.  an overlay) determines where the linker will place the entire segment
  22714.  (root or overlay). If your extracted .OBJ is in the overlay, all the
  22715.  run time gets put into the overlay.
  22716.  
  22717.  Consequently, the entry point of the overlay manager is put into the
  22718.  overlay and not in the root, so the overlay manager code (also in
  22719.  _TEXT) is not present in memory at start up. This causes the machine
  22720.  to hang.
  22721.  
  22722.  
  22723.  506. Calling C Run-Time from a Single-Threaded DLL Init Routine
  22724.  
  22725.  Product Version(s): 5.10
  22726.  Operating System:   OS/2
  22727.  Flags: ENDUSER |
  22728.  Last Modified: 17-JUL-1990    ArticleIdent: Q50759
  22729.  
  22730.  You can call the C run-time routines from within your initialization
  22731.  code for a single threaded dynamic link library (DLL).
  22732.  
  22733.  To accomplish this, you must ensure that the C run time itself is
  22734.  initialized prior to any run-time function call. This is easiest to do
  22735.  if you write your base initialization in assembly (as required), but
  22736.  then call a routine written in C that will perform the majority of
  22737.  your init code. This C routine must be declared as a extrn, far call
  22738.  in your assembly code, and defined/prototyped as such in your C init
  22739.  code.
  22740.  
  22741.  The following is a code example:
  22742.  
  22743.  extrn   MYINIT: far                 in the assembly init module.
  22744.  int far pascal MYINIT (...) ;       in the C init module.
  22745.  
  22746.  Once you have satisfied these items, you must then call C_INIT() from
  22747.  within your C init module. This must be done before any C run-time
  22748.  calls have been made. The C_INIT routine must also be prototyped as
  22749.  follows:
  22750.  
  22751.     int far pascal C_INIT (void) ;
  22752.  
  22753.  Note: This information applies to single-threaded DLLs only. You
  22754.  cannot call the C run time from the init code of a multi-threaded DLL.
  22755.  
  22756.  The example below details the steps necessary to call any C run-time
  22757.  routine from within your single-threaded DLL initialization code.
  22758.  
  22759.  This example involves the following files:
  22760.  
  22761.     PROJ.C          Source to the EXE that calls the DLL routine
  22762.     PROJ.LIB        Library created by IMPLIB (based on DLL.DEF)
  22763.                     [resolves the exported routine(s) from DLL.DLL]
  22764.     DLL.C           Source to the DLL, and the function FOOPER()
  22765.     DLL.DEF         Definitions file for the DLL
  22766.     ASMINIT.ASM     Assembly Init code
  22767.     CINIT.C         C Init code
  22768.  
  22769.  The source files to the .EXE and .DLL are standard for this type of
  22770.  programming.
  22771.  
  22772.  The initialization routines and their requirements are discussed
  22773.  below:
  22774.  
  22775.  ASMINIT.ASM
  22776.  -----------
  22777.  
  22778.       .model large
  22779.       extrn  MYINIT:far        ; Declare the C init routine as far.
  22780.       .code
  22781.       INIT    proc    far      ; Declare init proc....
  22782.  
  22783.               call    MYINIT   ; Call my C init code..
  22784.               ret              ; MYINIT exit code is in AX, so return.
  22785.  
  22786.       INIT    endp
  22787.               end     INIT     ; <--Specifies Entry Point for Init
  22788.                                ;    routine (reason why this must be
  22789.                                ;    in assembly).
  22790.  
  22791.  CINIT.C
  22792.  -------
  22793.  
  22794.  #include <stdio.h>
  22795.  
  22796.       // Prototype C Run-Time init function, and my C init code...
  22797.       int far pascal C_INIT (void) ;
  22798.       int far pascal MYINIT (void) ;
  22799.  
  22800.       int far pascal MYINIT (void)
  22801.       {
  22802.         int RetVal ;
  22803.  
  22804.         // Call the C Run-Time Initialization code..
  22805.         RetVal = C_INIT () ;
  22806.  
  22807.         // Calls to the C Run-Time are now valid...
  22808.         printf ("Hello from the DLL init code...\n") ;
  22809.  
  22810.         // other C Run-Time calls can be made here...
  22811.  
  22812.         // exit with return value from this initialization code...
  22813.         return (RetVal) ;
  22814.       }
  22815.  
  22816.  The source to the remaining files are listed below:
  22817.  
  22818.  PROJ.C
  22819.  ------
  22820.  
  22821.  #include <stdio.h>
  22822.  
  22823.  void far pascal FOOPER (int, int) ;
  22824.  void main (void)
  22825.  {
  22826.    printf ("Hello from Main().  Calling DLL routine...\n") ;
  22827.    FOOPER (1, 2) ;
  22828.    printf ("\nDone.\n") ;
  22829.  }
  22830.  
  22831.  DLL.C
  22832.  -----
  22833.  
  22834.  #include <stdio.h>
  22835.  
  22836.  void far pascal FOOPER (int, int) ;
  22837.  void far pascal FOOPER (int x, int y)
  22838.  {
  22839.    printf ("Hello from DLL routine 'Fooper'.\n") ;
  22840.  }
  22841.  
  22842.  DLL.DEF
  22843.  -------
  22844.  
  22845.  LIBRARY     DLL  INITINSTANCE
  22846.  DESCRIPTION 'single threaded DLL showing C Run-Time in Init Code'
  22847.  DATA        MULTIPLE
  22848.  EXPORTS     FOOPER
  22849.  
  22850.  These files must be compiled and linked together as follows:
  22851.  
  22852.    cl   /Alfu /G2s /c dll.c
  22853.    masm /mx asminit.asm;
  22854.    cl   /Od /AL /G2 /c cinit.c
  22855.  
  22856.    link /CO dll asminit cinit,dll.dll/NOI,, \
  22857.             llibcdll.lib doscalls.lib, dll.def;
  22858.    copy dll.dll  c:\os2\dll
  22859.  
  22860.    cl      /AS /G2 /c proj.c
  22861.    implib  proj.lib  dll.def
  22862.  
  22863.    link /CO proj.obj, /NOI,, slibcep.lib proj.lib doscalls.lib/NOD ;
  22864.  
  22865.  
  22866.  507. Why After Edit, fopen with Mode "a" Doesn't Appear to Append
  22867.  
  22868.  Product Version(s): 5.10
  22869.  Operating System:   MS-DOS
  22870.  Flags: ENDUSER | S_QuickC S_QuickASM
  22871.  Last Modified: 30-NOV-1989    ArticleIdent: Q50793
  22872.  
  22873.  Problem:
  22874.  
  22875.  If I use edlin or Wordstar to edit a file, then call the fopen
  22876.  routine with the "a" option and append to the file, the appended
  22877.  text doesn't show up when I type the file.
  22878.  
  22879.  Response:
  22880.  
  22881.  Edlin and Wordstar are examples of editors that place a CTRL+Z
  22882.  character at the end of the file. Opening a file with the "a" option
  22883.  writes to the file beginning after the last character in the file (in
  22884.  this case, the CTRL+Z). If you then edit the file again with the same
  22885.  editor, the editor ignores all characters after the CTRL+Z.
  22886.  
  22887.  The DOS TYPE command will display all characters up to the first EOF.
  22888.  However, if you bring the file up in the M editor or Word, which
  22889.  display the CTRL+Z character as a normal character, you can see the
  22890.  appended text and, if you want, delete the CTRL+Z character.
  22891.  
  22892.  If you fopen a file with the "a+" mode, the CTRL+Z character is
  22893.  deleted at the end of the file, and appended text can be seen in any
  22894.  editor or by using the DOS TYPE command.
  22895.  
  22896.  The following code demonstrates this behavior:
  22897.  
  22898.  #include <stdio.h>
  22899.  #include <time.h>
  22900.  
  22901.  void main(void)
  22902.  {
  22903.       FILE *fp;
  22904.       int num;
  22905.       time_t system_time;
  22906.  
  22907.       fp = fopen("out.dat","a");          /* change to "a+" to fix */
  22908.       time(&system_time);                 /* to demonstrate last append */
  22909.       num = fprintf(fp, "Writing to file at %s\n",
  22910.                           ctime(&system_time));
  22911.       num = fclose(fp);
  22912.  }
  22913.  
  22914.  Run this program once to write the current system time to the output
  22915.  file. Then edlin "out.dat". You do not need to add any lines, just
  22916.  open the file and then end the session. Then run the program again.
  22917.  Type "out.dat", and notice that you still see only the first output
  22918.  time.
  22919.  
  22920.  Changing the fopen "a" to "a+" and rebuilding the program will
  22921.  demonstrate the solution.
  22922.  
  22923.  
  22924.  508. Time and Date Are Written When File Is Flushed
  22925.  
  22926.  Product Version(s): 5.10
  22927.  Operating System:   MS-DOS
  22928.  Flags: ENDUSER | s_quickc
  22929.  Last Modified: 30-NOV-1989    ArticleIdent: Q51123
  22930.  
  22931.  Changing the time and date of a file with _dos_setftime may appear to
  22932.  fail if the file is opened for write and all data has not been written
  22933.  to disk. The DOS and OS/2 update file dates whenever a file gets
  22934.  modified. Therefore, changing a file date before the operating system
  22935.  has written all data to the physical disk may appear to be ignored.
  22936.  This is because the date is changed again when the file is closed or
  22937.  flushed if there is data still to be written.
  22938.  
  22939.  For example, the following program will try and modify the date and
  22940.  time of the output file to 6-1-89 10:00. Because the file has not been
  22941.  flushed or closed, it is likely that there is still data in the file
  22942.  buffer waiting to be written to disk. When the file is closed, the
  22943.  program will flush all remaining data to the disk, changing the date
  22944.  and time to the current date and time in the process.
  22945.  
  22946.  void main(void)
  22947.  {
  22948.    FILE *fp;
  22949.    fp = fopen( "outfile.txt", "wt" );
  22950.    fprintf( fp, "Start of file\n" );
  22951.    fprintf( fp, "End of file\n" );
  22952.    _dos_setftime( fileno( fp ), 0x12c1, 0x5000)  //  10:00  6-1-89
  22953.    fclose(fp);
  22954.  }
  22955.  
  22956.  One way to get around this feature of the operating system is to put a
  22957.  flush statement before the call to _dos_setftime. This ensures that
  22958.  all remaining data has been written to disk before the date is changed
  22959.  and the file is closed. The following program changes the date to
  22960.  6-1-89 10:00 successfully.
  22961.  
  22962.  void main(void)
  22963.  {
  22964.    FILE *fp;
  22965.    fp = fopen( "outfile.txt", "wt" );
  22966.    fprintf( fp, "Start of file\n" );
  22967.    fprintf( fp, "End of file\n" );
  22968.    fflush(fp);     //       <---- flush the data to disk
  22969.    _dos_setftime( fileno( fp ), 0x12c1, 0x5000)  //  10:00  6-1-89
  22970.    fclose(fp);
  22971.  }
  22972.  
  22973.  
  22974.  509. Formal Parameters Default to Type int
  22975.  
  22976.  Product Version(s): 5.10   | 5.10
  22977.  Operating System:   MS-DOS | OS/2
  22978.  Flags: ENDUSER | S_QUICKC
  22979.  Last Modified: 30-NOV-1989    ArticleIdent: Q51198
  22980.  
  22981.  Question:
  22982.  
  22983.  Why doesn't the compiler generate an error for the following code?
  22984.  
  22985.     void main (voida)
  22986.     {
  22987.     }
  22988.  
  22989.  The variable "voida" is not referenced.
  22990.  
  22991.  Response:
  22992.  
  22993.  The C and QuickC compilers don't generate an error because the
  22994.  variable "voida" defaults to a variable of type int. The compilers
  22995.  understand the above function definition since they recognize the "old
  22996.  style" of ANSI C declarations as well as the new. In general, the
  22997.  equivalents of the above code are as follows:
  22998.  
  22999.     Old Style                           New Style
  23000.     ---------                           ---------
  23001.  
  23002.     void function (voida)               void function (int voida)
  23003.     int voida  <- default if missing    {
  23004.     {                                   }
  23005.     }
  23006.  
  23007.  Please refer to "The C Programming Language" by Brian Kernighan and
  23008.  Dennis Ritchie for a discussion on differences between old and new
  23009.  style with regards to function definition.
  23010.  
  23011.  
  23012.  510. C 5.00 and C 5.10 Compiler Exit Codes
  23013.  
  23014.  Product Version(s): 5.00 5.10 | 5.10
  23015.  Operating System:   MS-DOS    | OS/2
  23016.  Flags: ENDUSER | S_EDITOR
  23017.  Last Modified: 30-NOV-1989    ArticleIdent: Q51297
  23018.  
  23019.  The return codes from the compiler are documented in the "Microsoft C
  23020.  Optimizing Compiler User's Guide," Appendix A.3. They are as follows:
  23021.  
  23022.     Code       Meaning
  23023.     ----       -------
  23024.     0          No fatal error
  23025.     2          Program error (such as compiler error
  23026.     4          System level error (such as out of disk
  23027.                   space or compiler internal error)
  23028.  
  23029.  The compiler returns the same exit codes when you run it from inside
  23030.  the Microsoft Editor Version 1.00.
  23031.  
  23032.  
  23033.  511. tmpfile() Creates Temporary File in the Root Directory
  23034.  
  23035.  Product Version(s): 5.10
  23036.  Operating System:   MS-DOS
  23037.  Flags: ENDUSER | S_QuickC Novell docsup
  23038.  Last Modified: 30-NOV-1989    ArticleIdent: Q51326
  23039.  
  23040.  The Microsoft C Version 5.10 run-time library function tmpfile()
  23041.  creates a temporary file in the root directory of the current drive.
  23042.  This file has read/write access and is automatically deleted when the
  23043.  file is closed.
  23044.  
  23045.  The documentation for this function implies that the file will be
  23046.  created in the current working directory. This is not the case; the
  23047.  file will exist only in the root directory. To create a temporary file
  23048.  in a different directory, use the functions tmpname() or tempname() in
  23049.  conjunction with fopen().
  23050.  
  23051.  Some obscure side effects can occur on some systems as a result of
  23052.  tmpfile() creating a file in the root directory. On a network, you
  23053.  must have read/write privileges for the root directory of your current
  23054.  drive. Without these rights, tmpfile() will fail to open the temporary
  23055.  file, returning a NULL in the process.
  23056.  
  23057.  Another possible reason tmpfile() might fail is if the root directory
  23058.  is full. DOS only allows a limited amount of file entries in the root
  23059.  directory depending on the disk format; therefore, if the root is
  23060.  full, you must delete some files before you use tmpfile().
  23061.  
  23062.  
  23063.  512. strtok(): C Function -- Documentation Supplement
  23064.  
  23065.  Product Version(s): 5.00 5.10 | 5.10
  23066.  Operating System:   MS-DOS    | OS/2
  23067.  Flags: ENDUSER | S_QuickC docsup
  23068.  Last Modified: 30-NOV-1989    ArticleIdent: Q51327
  23069.  
  23070.  The strtok() function takes two strings as arguments. The first is a
  23071.  series of zero or more tokens separated by delimiters defined by the
  23072.  second string. The first call to strtok() returns a pointer to the
  23073.  first token in the first argument. To get the next token in the
  23074.  original string, a call to strtok() must be made with NULL as the
  23075.  first argument that tells strtok() to search for the next token in
  23076.  the previous token string.
  23077.  
  23078.  Keep the following information in mind when using strtok():
  23079.  
  23080.  1. strtok() will replace a delimiter in the original string with a
  23081.     NULL each time the function is called using the same string, so the
  23082.     original string is modified by the use of strtok().
  23083.  
  23084.  2. The second argument to strtok() can be changed at any time to a
  23085.     different delimiter.
  23086.  
  23087.  3. Only single characters are considered to be delimiters.
  23088.  
  23089.  On the first call to strtok(), the function searches the string
  23090.  argument given as the first parameter for any token delimiter defined
  23091.  in the second string argument. Any further call to strtok() with NULL
  23092.  as the first argument will return a pointer to the next token in the
  23093.  original string. The following sample program from Page 603 of the
  23094.  "Microsoft C Run-Time Library Reference" manual for Version 5.10 shows
  23095.  how strtok() searches a token string:
  23096.  
  23097.  #include <string.h>
  23098.  #include <stdio.h>
  23099.  
  23100.  char *string = "a string,of ,,tokens";
  23101.  char *token;
  23102.  
  23103.  void main(void)
  23104.  {
  23105.          token = strtok(string," ,"); /*there are two delimiters here*/
  23106.          while (token != NULL){
  23107.                  printf("The token is:  %s\n", token);
  23108.                  token = strtok(NULL," ,");
  23109.          }
  23110.  }
  23111.  
  23112.  The output of this program is as follows:
  23113.  
  23114.     The token is: a
  23115.     The token is: string
  23116.     The token is: of
  23117.     The token is: tokens
  23118.  
  23119.  The following is a sample representation of the area in memory around
  23120.  the token pointer during execution of the above program. Note the
  23121.  replacement of the delimiter with a NULL character each time a token
  23122.  is found:
  23123.  
  23124.     -------------------------------------------------------------
  23125.     |a |  |s |t |r |i |n |g |, |o |f |  |, |, |t |o |k |e |n |s |
  23126.     -------------------------------------------------------------
  23127.     This is the original string before the first call to strtok()
  23128.  
  23129.     -------------------------------------------------------------
  23130.     |a |\0|s |t |r |i |n |g |, |o |f |  |, |, |t |o |k |e |n |s |
  23131.     -------------------------------------------------------------
  23132.      ^----- token will point here on the first call
  23133.  
  23134.     -------------------------------------------------------------
  23135.     |a |\0|s |t |r |i |n |g |\0|o |f |  |, |, |t |o |k |e |n |s |
  23136.     -------------------------------------------------------------
  23137.            ^------ token will point here on the second call
  23138.  
  23139.     -------------------------------------------------------------
  23140.     |a |\0|s |t |r |i |n |g |\0|o |f |\0|, |, |t |o |k |e |n |s |
  23141.     -------------------------------------------------------------
  23142.                                 ^----- token will point here on
  23143.                                        the third call
  23144.  
  23145.                                  (etc.)
  23146.  
  23147.  
  23148.  513. How to Calculate Available File Handles at Run Time
  23149.  
  23150.  Product Version(s): 5.10   | 5.10
  23151.  Operating System:   MS-DOS | OS/2
  23152.  Flags: ENDUSER | S_QUICKC
  23153.  Last Modified: 14-MAR-1990    ArticleIdent: Q51434
  23154.  
  23155.  The following piece of code allows you to find out how many file
  23156.  handles are available at run time for a particular process. The
  23157.  function makes use of the predefined pointers _iob and _lastiob, which
  23158.  are set to point to the first and the last input/output information
  23159.  blocks, respectively. The I/O blocks are examined to determine whether
  23160.  they are in use, and a total number of available file handles is
  23161.  produced. There is no equivalent C library function currently
  23162.  available.
  23163.  
  23164.  Note: This is not necessarily an indication of the maximum number of
  23165.  physical files that can be opened. The system-wide limit is set in DOS
  23166.  by the FILES=?? in the CONFIG.SYS file. In OS/2, it is arbitrarily
  23167.  governed by system resources and is modified for each process by
  23168.  DosSetMaxFH().
  23169.  
  23170.  Code Example
  23171.  ------------
  23172.  
  23173.  #define FILE struct _iobuf
  23174.  #ifndef NO_EXT_KEYS           /* extensions enabled */
  23175.      #define _CDECL  cdecl
  23176.      #define _NEAR   near
  23177.  #else                         /* extensions not enabled */
  23178.      #define _CDECL
  23179.      #define _NEAR
  23180.  #endif                        /* NO_EXT_KEYS */
  23181.  
  23182.  #define _IOREAD 0x01          /* Open for read bit */
  23183.  #define _IOWRT  0x02          /* Open for write bit */
  23184.  #define _IORW   0x80          /* Open for read/write bit */
  23185.  
  23186.  FILE                          /* File handle table entry */
  23187.  {
  23188.      char *_ptr;
  23189.      int   _cnt;
  23190.      char *_base;
  23191.      char  _flag;
  23192.      char  _file;
  23193.   }_NEAR _CDECL _iob[], /*Set to first I/O block at runtime*/
  23194.                 _lastiob[];   /* Set to last I/O block */
  23195.  
  23196.  /*
  23197.     All of the above definitions were taken from the STDIO.H header
  23198.     file except for _lastiob[], which is not defined. This information
  23199.     was extracted to make the example more clear.
  23200.  */
  23201.  
  23202.  /*
  23203.     The following macro will check the availability of a file handle
  23204.     by examining the _flag member of the I/O block
  23205.  */
  23206.  
  23207.  #define inuse(s) ((s)->_flag & (_IOREAD|_IOWRT|_IORW))
  23208.  
  23209.  /*
  23210.     The following routine loops through the total number of I/O blocks
  23211.     and checks the flags to see if it is used or not. The number of
  23212.     unused handles is returned, which can be 1 to the maximum number of
  23213.     file handles as set by the operating system or the FILES=xx command
  23214.     in the CONFIG.SYS file.
  23215.  */
  23216.  
  23217.  int Number_Of_Handles(void)
  23218.  {
  23219.     FILE *stream = _iob;
  23220.     int count;
  23221.  
  23222.     count = 0;
  23223.     do
  23224.        if (inuse(stream)) count++;
  23225.     while(stream++ < _lastiob);
  23226.  
  23227.     return(((_lastiob - _iob)+1)-count);
  23228.  }
  23229.  
  23230.  void main(void)
  23231.  {
  23232.     int i;
  23233.  
  23234.     i = Number_Of_Handles();
  23235.  /* i is now set to the number of available file handles */
  23236.  }
  23237.  
  23238.  The table of I/O blocks that is being checked here was allocated at
  23239.  run time according to the maximum number of file handles allowed per
  23240.  process.
  23241.  
  23242.  
  23243.  514. Character Parameters May Be Prototyped As Integers
  23244.  
  23245.  Product Version(s): 5.10   | 5.10
  23246.  Operating System:   MS-DOS | OS/2
  23247.  Flags: ENDUSER | S_QUICKC
  23248.  Last Modified: 14-MAR-1990    ArticleIdent: Q51474
  23249.  
  23250.  There are some functions in the run-time library that take character
  23251.  values as parameters (i.e., memccpy, memset, etc.) and that are
  23252.  prototyped as taking integers. This is not a documentation error and
  23253.  your program will work correctly if a character value is passed in the
  23254.  place of the integer parameter (automatic casting takes care of this).
  23255.  
  23256.  The integer value is specified because when the compiler pushes
  23257.  parameters on the stack so that the function being called can use
  23258.  them, it always pushes them in word increments. In other words,
  23259.  regardless of whether the value is an integer or a character, 2 bytes
  23260.  will be pushed on the stack. Therefore, to simplify, the function is
  23261.  prototyped as receiving an integer.
  23262.  
  23263.  
  23264.  515. Missing Semicolon in Sample Average() Function
  23265.  
  23266.  Product Version(s): 5.00 5.10 | 5.10
  23267.  Operating System:   MS-DOS    | OS/2
  23268.  Flags: ENDUSER | docerr
  23269.  Last Modified: 14-MAR-1990    ArticleIdent: Q51486
  23270.  
  23271.  In the "Microsoft C Run-Time Library Reference," Page 634, there is a
  23272.  missing semicolon (;) in the sample function called average(). Add a
  23273.  semicolon at the end of the for-loop and the sample program will work
  23274.  properly.
  23275.  
  23276.  Note: There are two average() functions on Page 634, both need a
  23277.  semicolon at the end of the for-loop.
  23278.  
  23279.  
  23280.  516. OS/2 1.1 EXE May Fail under 1.2 Due to Small Thread Stack Size
  23281.  
  23282.  Product Version(s): 5.10
  23283.  Operating System:   OS/2
  23284.  Flags: ENDUSER |
  23285.  Last Modified: 20-DEC-1989    ArticleIdent: Q51512
  23286.  
  23287.  If a multithread program runs correctly under OS/2 Version 1.10, but
  23288.  the identical program fails under OS/2 Version 1.20, the problem may
  23289.  be the size of the thread stack. Under OS/2 1.20, a thread has more
  23290.  overhead and requires more space. If you maintain the recommended 2K
  23291.  minimum stack size for each thread, then you should never run into
  23292.  this problem.
  23293.  
  23294.  If your program has been running successfully under OS/2 1.10 with a
  23295.  thread stack that is smaller than 2K, and the program fails under OS/2
  23296.  1.20, then the first thing you should try is a larger thread stack
  23297.  size.
  23298.  
  23299.  Some of the early examples of multithreaded programming that were
  23300.  included in the OS/2 SDK used a thread stack size of 400 bytes. These
  23301.  programs run fine on the previous versions of OS/2, but fail with a
  23302.  trap 000C under OS/2 1.20. A check of the Intel 80286 documentation
  23303.  shows that 000C is a stack overflow problem.
  23304.  
  23305.  The exact increase necessary in thread stack size between OS/2 1.10
  23306.  and 1.20 was not determined, but increasing the stack to 1000 bytes
  23307.  allowed these SDK examples to run without problem. Regardless of the
  23308.  actual difference needed, the best thing to do is to maintain the
  23309.  minimum of at least a 2K thread stack to prevent problems in general.
  23310.  
  23311.  
  23312.  517. The /Gm Switch Really Does Move Constants to _CONST
  23313.  
  23314.  Product Version(s): 5.10   | 5.10
  23315.  Operating System:   MS-DOS | OS/2
  23316.  Flags: ENDUSER |
  23317.  Last Modified: 20-DEC-1989    ArticleIdent: Q51613
  23318.  
  23319.  Question:
  23320.  
  23321.  I am using the /Gm switch to move near string constants into the
  23322.  _CONST segment, but it doesn't seem to work properly. My program is
  23323.  shown below:
  23324.  
  23325.     char foo[] = "hello";
  23326.  
  23327.     void main(void)
  23328.     {
  23329.     }
  23330.  
  23331.  When I examine the map file generated, it tells me that foo is stored
  23332.  in _DATA. Why isn't the string constant "hello" being stored in
  23333.  _CONST?
  23334.  
  23335.  Response:
  23336.  
  23337.  The /Gm switch is behaving as it should. In the above case, the string
  23338.  constant "hello" is not stored as a constant, it is merely a shorthand
  23339.  way of initializing the array foo. For example,
  23340.  
  23341.     char foo[] = "hello";
  23342.  
  23343.  is equivalent to saying the following:
  23344.  
  23345.     char foo[] = {'h','e','l','l','o','\0'};
  23346.  
  23347.  The data in the array foo is not a string constant, and therefore,
  23348.  should not be moved to the _CONST section with the /Gm switch.
  23349.  
  23350.  The following code demonstrates a few string constants:
  23351.  
  23352.     #include <stdio.h>
  23353.  
  23354.     void main(void)
  23355.     {
  23356.         char array[] = "This is NOT a string constant.";
  23357.  
  23358.         char *foo = "This would be moved out to _CONST with /Gm";
  23359.         printf("This string will be moved to _CONST\n");
  23360.      }
  23361.  
  23362.  
  23363.  518. C4056: Overflow in Constant Arithmetic
  23364.  
  23365.  Product Version(s): 5.10   | 5.10
  23366.  Operating System:   MS-DOS | OS/2
  23367.  Flags: ENDUSER |
  23368.  Last Modified: 15-JAN-1990    ArticleIdent: Q51615
  23369.  
  23370.  The following code, when compiled at warning level 1 or greater,
  23371.  causes the Microsoft C 5.10 optimizing compiler to produce warning
  23372.  C4056:
  23373.  
  23374.     test.c(5) : warning C4056: overflow in constant arithmetic
  23375.  
  23376.  This warning occurs because the compiler is reordering the addition of
  23377.  the unsigned constants. This practice is no longer allowed according
  23378.  to the ANSI standard.
  23379.  
  23380.  To work around the problem, perform the arithmetic using long integer
  23381.  constants where necessary (use 65535L rather than 65535u, for
  23382.  example).
  23383.  
  23384.  QuickC Versions 2.00 and 2.01 handle this code correctly because these
  23385.  versions conform to more recent releases of the draft ANSI standard.
  23386.  
  23387.  The following is the code that produces the error:
  23388.  
  23389.     void
  23390.     test ( unsigned dummy )
  23391.     {
  23392.         dummy = 65535u - (dummy - 1);
  23393.     }
  23394.  
  23395.  
  23396.  519. Recursive CL Setting Can Cause D2002 Command-Line Error
  23397.  
  23398.  Product Version(s): 5.10   | 5.10
  23399.  Operating System:   MS-DOS | OS/2
  23400.  Flags: ENDUSER |
  23401.  Last Modified: 20-DEC-1989    ArticleIdent: Q51616
  23402.  
  23403.  The command-line error D2002 is produced by the Microsoft C 5.10
  23404.  optimizing compiler under certain circumstances when the CL
  23405.  environment variable is set recursively.
  23406.  
  23407.  The following situations cause the error:
  23408.  
  23409.     SET CL=CL
  23410.     CL -Ax woof.c           where x is M, C, or L
  23411.  
  23412.     SET CL=CL -Ax           where x is M, C, or L
  23413.     CL -Ay woof.c           where y is S, M, C, or L
  23414.  
  23415.  The error is produced even if -Ax is the same as -Ay in the latter
  23416.  case.
  23417.  
  23418.  D2002 will, of course, also occur when CL is set to a model other than
  23419.  the one specified or implied (-AS) on the command line.
  23420.  
  23421.  The following is the exact text of the error message:
  23422.  
  23423.     Command line error D2002 : a previously defined model
  23424.                                specification has been overridden
  23425.  
  23426.  
  23427.  520. No Warning When Passing Long to Int Prototyped Function
  23428.  
  23429.  Product Version(s): 5.10   | 5.00
  23430.  Operating System:   MS-DOS | OS/2
  23431.  Flags: ENDUSER | s_quickc s_quickasm
  23432.  Last Modified: 21-MAR-1990    ArticleIdent: Q51620
  23433.  
  23434.  If you prototype a function to accept an integer, and then pass a long
  23435.  integer to the function, Microsoft C Version 5.01 and Microsoft QuickC
  23436.  Versions 1.00, 1.01, 2.00, and 2.01 fail to give a warning about the
  23437.  data conversion if the value being passed is between -65536 and
  23438.  +65535. Instead, the value is converted to a valid integer (between
  23439.  -32768 and 32767) and passed to the function, causing unexpected
  23440.  results.
  23441.  
  23442.  This is also a problem with the Microsoft QuickAssembler Version 2.01.
  23443.  
  23444.  The following code demonstrates this problem:
  23445.  
  23446.  #include <stdio.h>
  23447.  
  23448.  void func(int,int);
  23449.  
  23450.  void main(void)
  23451.  {
  23452.       func(50000L,1L);    /* Can also pass in (long)50000,long(1)     */
  23453.  }                        /* and have no warnings.                    */
  23454.                           /* Try changing to 100000, notice correct   */
  23455.                           /* warning.                                 */
  23456.  void func(int a, int b)
  23457.  {
  23458.       printf("a=%d  b=%d",a,b);
  23459.  }
  23460.  
  23461.  If you declare two long integers and pass them to func, as in the
  23462.  following, you receive a data conversion warning as expected:
  23463.  
  23464.     long a=50000,b=1;
  23465.     func(a,b);
  23466.  
  23467.  
  23468.  521. How to Use the Token Pasting Operator in Microsoft C
  23469.  
  23470.  Product Version(s): 5.10   | 5.10
  23471.  Operating System:   MS-DOS | OS/2
  23472.  Flags: ENDUSER | S_QUICKC S_QUICKASM 2.00 2.01
  23473.  Last Modified: 15-MAR-1990    ArticleIdent: Q51712
  23474.  
  23475.  The token pasting operator (##) is used to replace tokens within a
  23476.  preprocessor string. The (##) can be used to mark off the first
  23477.  portion of the string as a token, the last part of the string as a
  23478.  token, or the middle of a string as a portion. See the examples shown
  23479.  below.
  23480.  
  23481.  The token pasting operator cannot be the first or the last token in a
  23482.  preprocessor string (see Page 197 of the "Microsoft C Language
  23483.  Reference" manual for Version 5.10). The first example below (GLUE)
  23484.  demonstrates the use of the token pasting operator to concatenate two
  23485.  tokens. There is a replaceable token in front of the operator and one
  23486.  following the operator. The token pasting operator effectively divides
  23487.  the string into the two pieces.
  23488.  
  23489.  A more complex situation arises when using the token pasting operator
  23490.  to replace a token embedded within a string (for example,
  23491.  THIS_IS_A_size_TOKEN, where size could be replaced with either large
  23492.  or small); the token to be replaced must be surrounded by token
  23493.  pasting operators (##). This is necessary only when the token to be
  23494.  replaced is completely embedded in another string (see Example 2).
  23495.  Normally, the space character is used as one of the token markers,
  23496.  while the (##) marks the other end. Only in this specific case (an
  23497.  embedded token) is more than one token pasting operator needed.
  23498.  
  23499.  For more information, please see the ANSI Draft Proposal for the C
  23500.  programming language (Document Number X3J11/88-159, 7 December 1988),
  23501.  Page 93, or the "Microsoft C Language Reference" manual for Version
  23502.  5.10, Page 197.
  23503.  
  23504.  /*
  23505.      PASTE.C: Demonstrates the use of the token pasting operator.
  23506.  */
  23507.  /*
  23508.      Example 1 definition.
  23509.      This definition will replace the token "a" from the beginning
  23510.      of the string and "b" from the tail of the string.
  23511.  */
  23512.  
  23513.  #define GLUE(a,b) a##b
  23514.  
  23515.  /*
  23516.     These are the defines for Example 2.
  23517.     Calling print with either LARGE or SMALL will then change
  23518.     the PRINT macro to call the proper PRINT_..._SIZE macro.
  23519.  */
  23520.  #define PRINT_LARGE_SIZE(val) printf("The large size is %d\n",val)
  23521.  #define PRINT_SMALL_SIZE(val) printf("The small size is %d\n",val)
  23522.  #define PRINT(size,val) PRINT_##size##_SIZE(val)
  23523.  
  23524.  void main ( void )
  23525.  
  23526.  {
  23527.      char *varsrc = "Hello!" ;
  23528.      char *vardest = "      " ;
  23529.  
  23530.  /*
  23531.      Example #1: Tokens at beginning and end of string
  23532.  */
  23533.  
  23534.      strcpy(GLUE(var,dest),GLUE(var,src)) ;
  23535.      printf("%s\n", GLUE(var,dest)) ;
  23536.  
  23537.  /*
  23538.      Example #2: Token embedded in string
  23539.  */
  23540.  
  23541.      PRINT(LARGE, 2) ; /* Calls the printf() for large sizes. */
  23542.      PRINT(SMALL, 1) ; /* Calls the printf() for small sizes. */
  23543.  }
  23544.  
  23545.  The following is the corresponding .i (preprocessed file). This file
  23546.  can be generated by using -P option at compile time (cl -P paste.c).
  23547.  
  23548.  void main ( void )
  23549.  
  23550.  {
  23551.      char *varsrc = "Hello!" ;
  23552.      char *vardest = "      " ;
  23553.  
  23554.      strcpy(vardest,varsrc) ;
  23555.      printf("%s\n", vardest) ;
  23556.  
  23557.      printf("The large size is %d\n",2) ;
  23558.      printf("The small size is %d\n",1) ;
  23559.  }
  23560.  
  23561.  
  23562.  522. Clarification of the /H Identifier Length Option
  23563.  
  23564.  Product Version(s): 5.10   | 5.10
  23565.  Operating System:   MS-DOS | OS/2
  23566.  Flags: ENDUSER | S_QUICKC docerr
  23567.  Last Modified: 15-MAR-1990    ArticleIdent: Q51724
  23568.  
  23569.  The /H option is used to set the maximum length of identifiers in
  23570.  Microsoft C Version 5.10. Using /H can only decrease the maximum
  23571.  allowable length of identifiers, not increase it. An identifier
  23572.  declared with the CDECL type has an underscore (_) appended to the
  23573.  front at compile time. This character is part of the identifier and
  23574.  takes a significant location. Therefore, the maximum length of an
  23575.  identifier declared with the standard C declaration syntax is 32
  23576.  characters (the compiler limit on Page 280 of the "Microsoft C User's
  23577.  Guide" for Version 5.10 specifies 31 characters, which does not
  23578.  include the underscore).
  23579.  
  23580.  The following example shows how using /H can actually introduce errors
  23581.  if identifier lengths are limited to much:
  23582.  
  23583.  /* When compiled with /H5, the following code will produce
  23584.  the error 'L2025: _func : symbol defined more than once'. */
  23585.  
  23586.  void func1(void);
  23587.  void func2(void);
  23588.  
  23589.  void main(void)
  23590.  {
  23591.       func1();
  23592.  }
  23593.  
  23594.  void func1(void)
  23595.  {
  23596.  }
  23597.  
  23598.  void func2(void)
  23599.  {
  23600.  }
  23601.  
  23602.  You must also be careful when using the /H option because of
  23603.  predefined compiler identifiers. If the maximum identifier length is
  23604.  too small, certain predefined identifiers will be unresolved as well
  23605.  as certain library function calls. For example, if the printf function
  23606.  is used and the option /H5 is specified at compile time, the symbol
  23607.  _prin will be created in order to reference printf, and this will not
  23608.  be found in the library.
  23609.  
  23610.  
  23611.  523. Manual Correction for MASM Returning Single or Double to BASIC
  23612.  
  23613.  Product Version(s): 5.00   | 5.00
  23614.  Operating System:   MS-DOS | OS/2
  23615.  Flags: ENDUSER | docerr B_BasicCom H_MASM B_QuickBas
  23616.  Last Modified: 15-MAR-1990    ArticleIdent: Q51728
  23617.  
  23618.  The following information is relevant to BASIC programmers who want
  23619.  their BASIC programs to correctly invoke assembly language functions
  23620.  that return single- or double-precision floating-point values.
  23621.  
  23622.  The following two corrections apply to Page 78 of the "Microsoft
  23623.  Mixed-Language Programming Guide," which comes with Microsoft C
  23624.  Compiler Version 5.00 and with Microsoft Macro Assembler (MASM)
  23625.  Version 5.00 (but does not come with BASIC):
  23626.  
  23627.  1. In Section 6.1.6, in the second paragraph, the phrase "BASIC or"
  23628.     should be deleted.
  23629.  
  23630.  2. In the third paragraph, change the phrase "FORTRAN or Pascal"
  23631.     to "BASIC, FORTRAN, or Pascal".
  23632.  
  23633.  This documentation error was corrected in the "Microsoft
  23634.  Mixed-Language Programming Guide" supplied with Versions 5.10 of
  23635.  Microsoft C and Microsoft Macro Assembler.
  23636.  
  23637.  The first sentence in the second paragraph in Section 6.1.6 on Page 78
  23638.  should thus read as follows:
  23639.  
  23640.     When the return value is larger than 4 bytes, a procedure called
  23641.     by C must allocate space for the return value and then place its
  23642.     address in DX:AX.
  23643.  
  23644.  The first sentence in the third paragraph in Section 6.1.6 on Page 78
  23645.  should thus read as follows:
  23646.  
  23647.     If your assembly procedure is called by BASIC, FORTRAN, or Pascal,
  23648.     then it must use a special convention in order to return
  23649.     floating-point values, records and arrays, and values larger than
  23650.     4 bytes.
  23651.  
  23652.  For a complete guide for passing parameters and invoking functions
  23653.  between BASIC and assembly language, search in the Microsoft Knowledge
  23654.  Base for the following word: BAS2MASM.
  23655.  
  23656.  
  23657.  524. Clock Function Sets errno
  23658.  
  23659.  Product Version(s): 5.00 5.10 | 5.00 5.10
  23660.  Operating System:   MS-DOS    | OS/2
  23661.  Flags: ENDUSER | s_quickc s_quickasm
  23662.  Last Modified: 16-JAN-1990    ArticleIdent: Q51735
  23663.  
  23664.  Question:
  23665.  
  23666.  Why does the clock function set errno?
  23667.  
  23668.  Response:
  23669.  
  23670.  The clock function uses intdos() to read the system date and time.
  23671.  When intdos() calls the date/time interrupt, the carry flag is set
  23672.  upon return. The intdos() function interprets the carry flag as an
  23673.  error and sets errno to the value in AL. In the case of a request for
  23674.  the system date, AL (and therefore, errno) contains the day of the
  23675.  week.
  23676.  
  23677.  
  23678.  525. Spawned Process Runs Out of Environment Space
  23679.  
  23680.  Product Version(s): 5.10
  23681.  Operating System:   MS-DOS
  23682.  Flags: ENDUSER | s_quickc s_quickasm
  23683.  Last Modified: 20-DEC-1989    ArticleIdent: Q51742
  23684.  
  23685.  Using spawn to create a child process, then attempting to increase the
  23686.  environment space of the child (by adding a new environment variable
  23687.  or expanding an existing environment variable) results in an "Out of
  23688.  Environment Space" error.
  23689.  
  23690.  This problem does NOT happen under OS/2.
  23691.  
  23692.  The following program(s) illustrates this behavior:
  23693.  
  23694.  /*-----------------------------------------------------------------*/
  23695.  /*-----------------------------------------------------------------*/
  23696.  parent.c  This will call the child process (child) with the spawnlp
  23697.            function.
  23698.  /*-----------------------------------------------------------------*/
  23699.  
  23700.  #include <stdio.h>
  23701.  #include <process.h>
  23702.  
  23703.  void main (void);
  23704.  
  23705.  void main (void)
  23706.  {
  23707.      printf ("In the parent process\n");
  23708.  
  23709.      spawnlp (P_WAIT, "child.exe", "child", NULL);
  23710.  
  23711.      printf ("\nAnd back to the parent process.\n");
  23712.  }
  23713.  
  23714.  /*-----------------------------------------------------------------*/
  23715.  child.c Called by parent.c, uses the system function to call a batch
  23716.          file (BATCH.BAT) to attempt to set a new environment variable.
  23717.  
  23718.  /*-----------------------------------------------------------------*/
  23719.  #include <stdio.h>
  23720.  #include <process.h>
  23721.  #include <conio.h>
  23722.  #include <errno.h>
  23723.  
  23724.  void main (void);
  23725.  
  23726.  void main (void)
  23727.  {
  23728.      printf ("At child process...\n");
  23729.      system ("batch.bat");
  23730.      getch ();
  23731.  }
  23732.  
  23733.  /*-----------------------------------------------------------------*/
  23734.  BATCH.BAT  The batch file, which is called by the child process
  23735.              (CHILD.EXE). It just shows the environment variables,
  23736.              attempts to set another environment variable, then shows
  23737.              the environment variables one more time.
  23738.  /*-----------------------------------------------------------------*/
  23739.  set
  23740.  set blah=thisisatestonlyatestsoitdoesnotreallymatter
  23741.  set
  23742.  /*----------------------------------------------------------------------*/
  23743.  
  23744.  Parent will spawn child, which in turn spawns (through system)
  23745.  BATCH.BAT. The idea is to show that when BATCH.BAT is called, an "Out
  23746.  of Environment Space" error will be given. Yet, if BATCH.BAT is run
  23747.  from DOS, no such error is issued.
  23748.  
  23749.  To work around this problem, set up a dummy environment variable that
  23750.  is large enough to hold the new environment variable you plan to use
  23751.  in the spawned process. When the child process is called, you can then
  23752.  set the dummy variable to null (with a "set dummy="), then you can set
  23753.  your processes environment variable. Please note that this will change
  23754.  the dummy environment variable for the child only, not the parent
  23755.  process.
  23756.  
  23757.  Under DOS, the child will get only enough space to hold the current
  23758.  environment variables, while under OS/2, the segment that holds the
  23759.  environment can usually be expanded.
  23760.  
  23761.  
  23762.  526. spawn Ignores arg0 with DOS 3.00 and Later
  23763.  
  23764.  Product Version(s): 5.10
  23765.  Operating System:   MS-DOS
  23766.  Flags: ENDUSER | S_QuickC S_QuickASM
  23767.  Last Modified: 16-JAN-1990    ArticleIdent: Q51768
  23768.  
  23769.  Question:
  23770.  
  23771.  Why is arg0 ignored when I use a spawn command under DOS?
  23772.  
  23773.  Response:
  23774.  
  23775.  Under DOS Versions 3.00 and later, the first argument (arg0) is used
  23776.  to hold the path and name of the program. The third parameter in a
  23777.  spawn command is arg0. Regardless of what you specify arg0 to be, DOS
  23778.  passes the path and name of the program to the child function. Under
  23779.  DOS 2.x, arg0 is not defined.
  23780.  
  23781.  Under OS/2, this is not the case; arg0 is passed as specified with the
  23782.  spawn command.
  23783.  
  23784.  
  23785.  527. Casting Large Double to Float Gives Compile or Run-Time Error
  23786.  
  23787.  Product Version(s): 5.10   | 5.10
  23788.  Operating System:   MS-DOS | OS/2
  23789.  Flags: ENDUSER | s_quickc
  23790.  Last Modified: 10-JAN-1990    ArticleIdent: Q52103
  23791.  
  23792.  Casts of double numbers (greater than 3.4E+38) to float numbers can
  23793.  cause serious problems at compile time or at run time. Although this
  23794.  is expected behavior, it is inconsistent with typical overflow casting
  23795.  in that no errors or warnings are produced by the compiler when
  23796.  nonfloat overflow casts are made.
  23797.  
  23798.  In addition, overflowing a float by casting it to a double constant
  23799.  may cause the compiler to generate several lines of random characters.
  23800.  
  23801.  Microsoft has confirmed this random character generation to be a
  23802.  problem with C Version 5.10. We are researching this problem and will
  23803.  post new information as it becomes available.
  23804.  
  23805.  If a constant that is greater than 3.4E+38 (the maximum float) is cast
  23806.  to a float, the compiler will fail with the following error:
  23807.  
  23808.     fatal error C1045: floating point overflow
  23809.  
  23810.  The following code sample demonstrates the compile error:
  23811.  
  23812.       /* This code when compiled will produce compiler error code
  23813.          C1045. */
  23814.  
  23815.       void main(void)
  23816.       {
  23817.            float f;
  23818.  
  23819.            f = (float)6e39;
  23820.            /* All numbers up to 3.4e38 work fine */
  23821.       }
  23822.  
  23823.  If a double return value (greater than 3.4E+38) is cast to a float,
  23824.  the following run-time error message is displayed:
  23825.  
  23826.     run-time error M6104: MATH
  23827.     -floating-point error: overflow
  23828.  
  23829.  This following code sample demonstrates the run-time error:
  23830.  
  23831.       /* This code will compile fine but produces a run-time error
  23832.          M6104. */
  23833.  
  23834.       #include <stdlib.h>
  23835.  
  23836.       void main(void)
  23837.       {
  23838.           float f;
  23839.  
  23840.           f = (float)atof("6e39");
  23841.           /* Once again, all numbers up to 3.4e38 work fine */
  23842.       }
  23843.  
  23844.  On the other hand, the following integer cast overflow demonstrates
  23845.  that on a nonfloating point cast overflow, no errors are produced:
  23846.  
  23847.       /* The following code produces no compiler errors, warnings
  23848.          (even at warning level 3), or run-time errors. */
  23849.  
  23850.       #include <stdio.h>
  23851.  
  23852.       void main(void)
  23853.       {
  23854.           int i;
  23855.  
  23856.           i = (int)70000;
  23857.           /* The signed integer i is overflowed in this case and will
  23858.              probably produce unintended results. */
  23859.       }
  23860.  
  23861.  There is no workaround regarding the casting of double constants to
  23862.  floats at compile time other than eliminating the offending cast from
  23863.  the code. On the other hand, the problem with the floating point
  23864.  overflow error at run time can be caught by using the signal()
  23865.  function to trap floating point exceptions. However, both problems can
  23866.  be avoided if you ensure that a value greater than 3.4E+38 (maximum
  23867.  float value as determined by the IEEE standard for 4 byte floating
  23868.  point numbers) is never assigned to a float.
  23869.  
  23870.  
  23871.  528. Calling a User-Written Function from an ISR
  23872.  
  23873.  Product Version(s): 5.10
  23874.  Operating System:   MS-DOS
  23875.  Flags: ENDUSER | s_quickc
  23876.  Last Modified: 15-JAN-1990    ArticleIdent: Q52122
  23877.  
  23878.  It is possible to call a user-written function from an Interrupt
  23879.  Service Routine (ISR). However, there a few caveats, as shown below:
  23880.  
  23881.  1. Do not make any calls to stack checking routines.
  23882.  
  23883.  2. Do not assume DS=SS.
  23884.  
  23885.  There are other considerations that must be taken into account, such
  23886.  as which stack a program is running on, availability of space on the
  23887.  stack, etc. Because of these restrictions, there is a limit as to
  23888.  which C run-time functions can be used.
  23889.  
  23890.  Recommended reading for ISR programming is the "Microsoft Systems
  23891.  Journal," September 1988, Volume 3, Number 5. This issue of the MS
  23892.  Systems Journal contains an article for writing TSR (terminate and
  23893.  stay resident) programs with Microsoft C and covers such issues as
  23894.  stack considerations and program size. Also, see the Microsoft "MS-DOS
  23895.  Encyclopedia," Article 11, for more information.
  23896.  
  23897.  The following code provides a demonstration of an ISR calling a
  23898.  user-written function. The code revectors the keyboard interrupt (INT
  23899.  9H) and then waits for a hotkey to be pressed. If the hotkey is
  23900.  pressed, a message is displayed. Because of the above restrictions,
  23901.  the printf() family cannot be used. Therefore, a user-written
  23902.  function must be called to write the string.
  23903.  
  23904.  Note: The sample program does not go TSR because this would complicate
  23905.  the code. If the you want to modify it for TSR usage, please read the
  23906.  above articles.
  23907.  
  23908.  Sample Code
  23909.  -----------
  23910.  
  23911.  /* Compile with /Gs /Au */
  23912.  
  23913.  #include <dos.h>
  23914.  #include <bios.h>
  23915.  
  23916.  union REGS inregs, outregs;
  23917.  
  23918.  void (interrupt far *oldint9)();
  23919.  
  23920.  /* HOTKEY is CTRL+W */
  23921.  
  23922.  #define HOTKEY_CODE 0x11
  23923.  #define HOTKEY_STAT 0x4
  23924.  #define KEYPORT 0x60
  23925.  
  23926.  #define DOS_INT 0x21
  23927.  #define KEYSVC_INT 0x9
  23928.  #define DOS_PRINTSTRING 0x9
  23929.  
  23930.  void dos_puts( char *msg);
  23931.  void interrupt far newint9(void);
  23932.  
  23933.  void dos_puts( char *msg )
  23934.  {
  23935.  
  23936.     (void) _bios_keybrd( _KEYBRD_READ );
  23937.  
  23938.     inregs.h.ah = DOS_PRINTSTRING; /* DOS INT 21 Function 9h is    */
  23939.                                    /*    Display String            */
  23940.  
  23941.     inregs.x.dx = (int)msg; /* inregs.x.dx gets the segment        */
  23942.                             /* value of string to be output to crt */
  23943.  
  23944.     intdos( &inregs, &outregs );   /* INT 21 call to output string */
  23945.  }
  23946.  
  23947.  void interrupt far newint9(void)
  23948.  {
  23949.     static unsigned char keycode;
  23950.     static char active = 0;
  23951.  
  23952.     if (active)
  23953.        _chain_intr(oldint9);
  23954.  
  23955.     keycode = inp(KEYPORT);        /* Check for key at keyboard    */
  23956.  
  23957.     if (keycode != HOTKEY_CODE )   /* If key isn't HOTKEY,         */
  23958.        _chain_intr(oldint9);       /* pass to old handler          */
  23959.  
  23960.     if ( _bios_keybrd(_KEYBRD_SHIFTSTATUS) & HOTKEY_STAT )
  23961.     {
  23962.        active = 1;
  23963.        (*oldint9)();
  23964.        dos_puts("HOTKEY was pressed\r\n$");
  23965.        active = 0;
  23966.     }
  23967.     else
  23968.        _chain_intr(oldint9);
  23969.  }
  23970.  
  23971.  void main(void)
  23972.  {
  23973.     long x;
  23974.                                    /* Save old keyboard ISR */
  23975.     oldint9 = _dos_getvect( KEYSVC_INT );
  23976.                                    /* Set new keyboard ISR */
  23977.     _dos_setvect( KEYSVC_INT, newint9 );
  23978.                                    /* Loop awhile to let program run */
  23979.     for(x=0L; x <= 200000L; x++)
  23980.                                    /* Restore old ISR and exit */
  23981.        _dos_setvect( KEYSVC_INT, oldint9 );
  23982.  }
  23983.  
  23984.  
  23985.  529. C 5.1 Run-Time Reference Example for atan2() Is Missing ")"
  23986.  
  23987.  Product Version(s): 5.10    | 5.10
  23988.  Operating System:   MS-DOS  | OS/2
  23989.  Flags: ENDUSER | docerr
  23990.  Last Modified: 15-JAN-1990    ArticleIdent: Q57233
  23991.  
  23992.  On Page 123 in the "Microsoft C 5.1 Optimizing Compiler Run-Time
  23993.  Library Reference," there is a right parenthesis missing in the last
  23994.  line of the example program for the atan() and atan2() functions. The
  23995.  line should read as follows:
  23996.  
  23997.     printf("%.7f\n",atan2(-1.0,1.0));
  23998.  
  23999.  
  24000.  530. Workaround for Converting a Float/Double to a String
  24001.  
  24002.  Product Version(s): 5.10   | 5.10
  24003.  Operating System:   MS-DOS | OS/2
  24004.  Flags: ENDUSER | s_quickc s_quickasm
  24005.  Last Modified: 15-JAN-1990    ArticleIdent: Q57244
  24006.  
  24007.  Question:
  24008.  
  24009.  The gcvt() function returns an exponential number in the string even
  24010.  if the number fits in the specified precision when the number is of
  24011.  the form 0.0x, where x is any digit(s). Because of this behaviour with
  24012.  the gcvt() function, I am unable to convert my floating point number
  24013.  to a string in the format that I want. Is there another function I can
  24014.  use to convert a floating point number to a string?
  24015.  
  24016.  Response:
  24017.  
  24018.  Another function that converts a floating point number to a string is
  24019.  fcvt(). Unfortunately, it does not do all the conversion for you
  24020.  because it leaves out both the decimal point and the sign of the
  24021.  number.
  24022.  
  24023.  You can also use the sprintf() or printf() functions with the "%lf"
  24024.  format specifier to obtain the correct results. However, if you do not
  24025.  want to use any printf() constructs, supporting code is needed to
  24026.  completely convert the floating point number to a string. The
  24027.  following program shows one possible way this can be done, and the
  24028.  printf() statements can be replaced by puts() statements:
  24029.  
  24030.  Sample Program
  24031.  --------------
  24032.  
  24033.  #include <stdio.h>
  24034.  #include <stdlib.h>
  24035.  #include <malloc.h>
  24036.  #include <string.h>
  24037.  
  24038.  #define PRECISION   8
  24039.  
  24040.  char *double_to_char (double) ;
  24041.  
  24042.  char *temp2 ;
  24043.  
  24044.  void main (void)
  24045.  {
  24046.          temp2 = (char *) malloc (100) ;
  24047.          if (temp2 == NULL)
  24048.                  printf ("Hey, it didn't work (the malloc for temp)\n") ;
  24049.  
  24050.          temp2 = double_to_char ((double) 0.0004567891) ;
  24051.          printf ("temp = %s\n", temp2) ;
  24052.          temp2 = gcvt ((double) 0.0004567891, PRECISION, temp2) ;
  24053.          printf ("temp = %s\n", temp2) ;
  24054.  
  24055.          temp2 = double_to_char ((double) 123.564) ;
  24056.          printf ("temp = %s\n", temp2) ;
  24057.          temp2 = double_to_char ((double) -43.7864383846738) ;
  24058.          printf ("temp = %s", temp2) ;
  24059.  }
  24060.  
  24061.  /*  Translates a double to an ASCIIZ string
  24062.  */
  24063.  
  24064.  char *double_to_char (double number)
  24065.  {
  24066.          char *buffer,
  24067.                   *temp ;
  24068.  
  24069.          int  decimal_spot,
  24070.                   sign,
  24071.                   count,
  24072.                   current_location = 0 ;
  24073.  
  24074.          buffer = (char *) malloc (PRECISION + 3) ;
  24075.          temp   = (char *) malloc (PRECISION + 1) ;
  24076.          if (buffer == NULL || temp == NULL)
  24077.          {
  24078.                  printf ("Memory allocating attempt has failed in"
  24079.                          "'double_to_char'\n") ;
  24080.                  exit (-1) ;
  24081.          }
  24082.  
  24083.          temp = fcvt (number, PRECISION, &decimal_spot, &sign) ;
  24084.  
  24085.  /*      Force the number to be precise to only PRECISION digits, notice
  24086.                  that no rounding is done here...
  24087.  */
  24088.          temp [PRECISION] = '\0' ;
  24089.  
  24090.  /*      Is this a negative number ?, if so add a negative sign.
  24091.  */
  24092.          if (sign)
  24093.                  buffer [current_location++] = '-' ;
  24094.  
  24095.  /*      Now we need to put the decimal point in the correct place,
  24096.                  followed by the rest of the digits.
  24097.  */
  24098.          if (decimal_spot > 0)
  24099.          {
  24100.                  strncpy (&buffer [current_location], temp, decimal_spot) ;
  24101.                  buffer [decimal_spot + current_location] = '.' ;
  24102.                  strcpy (&buffer [decimal_spot + current_location + 1],
  24103.                                  &temp [decimal_spot]) ;
  24104.          }
  24105.          else
  24106.          {
  24107.                  buffer [current_location] = '.' ;
  24108.                  for (count = current_location;
  24109.                       count < abs (decimal_spot);
  24110.                       count++)
  24111.                          buffer [count + 1] = '0' ;
  24112.                  strcpy (&buffer [count + 1], temp) ;
  24113.          }
  24114.  
  24115.          return (buffer) ;
  24116.  }
  24117.  
  24118.  
  24119.  531. Intel Phone Number for Information About EMS Specifications
  24120.  
  24121.  Product Version(s): 5.10
  24122.  Operating System:   MS-DOS
  24123.  Flags: ENDUSER |
  24124.  Last Modified:  9-JAN-1990    ArticleIdent: Q57480
  24125.  
  24126.  Question:
  24127.  
  24128.  Can I access any memory beyond the base 640K on my machine within DOS?
  24129.  
  24130.  Response:
  24131.  
  24132.  If you have expanded memory and you have an EMS (Expanded Memory
  24133.  Specification) driver that conforms to LIM (Lotus/Intel/Microsoft)
  24134.  specifications, you can access memory beyond the base 640K available
  24135.  on your machine. For information about accessing this memory, contact
  24136.  Intel at (800) 538-3373 or (503) 629-7362.
  24137.  
  24138.  Intel will send you EMS specifications and documentation discussing
  24139.  writing code that uses EMS specifications, including a reprint of the
  24140.  March 1987 Microsoft Systems Journal article, "Expanded Memory:
  24141.  Writing Programs That Break the 640K Barrier."
  24142.  
  24143.  
  24144.  532. C Can Recognize up to 31 Characters of Any Name
  24145.  
  24146.  Product Version(s): 5.10   | 5.10
  24147.  Operating System:   MS-DOS | OS/2
  24148.  Flags: ENDUSER | docerr
  24149.  Last Modified:  9-JAN-1990    ArticleIdent: Q57481
  24150.  
  24151.  On Page 83, Section 6.3, Number 3, in the mixed-language guide of
  24152.  "Microsoft C 5.1 Optimizing Compiler CodeView and Utilities, Microsoft
  24153.  Editor, Mixed-Language Programming Guide," the following is
  24154.  incorrectly stated:
  24155.  
  24156.     C recognizes only the first eight characters of any name, so
  24157.     do not make names shared with C longer than eight characters.
  24158.  
  24159.  This statement is not true. C can recognize up to 31 characters.
  24160.  
  24161.  
  24162.  533. Displaying Only the Subdirectories with _A_SUBDIR
  24163.  
  24164.  Product Version(s): 5.10
  24165.  Operating System:   MS-DOS
  24166.  Flags: ENDUSER | s_quickc
  24167.  Last Modified: 15-JAN-1990    ArticleIdent: Q57549
  24168.  
  24169.  Question:
  24170.  
  24171.  I am using _dos_findfirst and _dos_findnext and using the _A_SUBDIR
  24172.  file attribute to find only the subdirectories. But I am getting not
  24173.  only the subdirectories, but also the filenames. Is there any way to
  24174.  have _dos_findfirst and _dos_findnext return just the subdirectories?
  24175.  
  24176.  Response:
  24177.  
  24178.  You can use _dos_findfirst and _dos_findnext, and by using _A_SUBDIR
  24179.  you can find just the subdirectories. Since the _A_SUBDIR attribute
  24180.  returns information about normal files as well as files with the
  24181.  subdirectory attribute, you must check each file to determine whether
  24182.  or not it is an actual subdirectory or a normal file. The following
  24183.  program demonstrates how to display just the subdirectories:
  24184.  
  24185.  Code Example
  24186.  ------------
  24187.  
  24188.  #include <stdio.h>
  24189.  #include <dos.h>
  24190.  #include <direct.h>
  24191.  
  24192.  void display_directory ( struct find_t *find );       /* Prototypes */
  24193.  
  24194.  void main( void )
  24195.  {
  24196.     struct find_t find;
  24197.     char buffer[67];
  24198.  
  24199.     getcwd (buffer, 66);
  24200.     printf ("Current Working Directory: %s\n", buffer);
  24201.  
  24202.   /* Find first matching file, then find additional matches. */
  24203.     if ( !_dos_findfirst( "*.*", _A_SUBDIR, &find ))
  24204.          display_directory ( &find );
  24205.     while( !_dos_findnext ( &find ))
  24206.          display_directory ( &find );
  24207.  }
  24208.  
  24209.  /* Displays Subdirectories in Current Directory */
  24210.  
  24211.  void display_directory ( struct find_t *pfind )
  24212.  {
  24213.     /* Determines whether the file is a subdirectory */
  24214.      if( pfind->attrib & _A_SUBDIR )
  24215.         printf ( "<DIR> %-8s\n", pfind->name );
  24216.  }
  24217.  
  24218.  
  24219.  534. Float Data Type May Cause Problems in TSR Applications
  24220.  
  24221.  Product Version(s): 5.00 5.10
  24222.  Operating System:   MS-DOS
  24223.  Flags: ENDUSER | s_quickc s_quickasm
  24224.  Last Modified: 26-FEB-1990    ArticleIdent: Q57586
  24225.  
  24226.  The following TSR (terminate and stay resident) interrupt handler does
  24227.  not execute properly when invoked. The floating point values produced
  24228.  are invalid. If you change the data type "float" to "double", the
  24229.  problem disappears.
  24230.  
  24231.  Code Example
  24232.  ------------
  24233.  
  24234.  #include <stdio.h>
  24235.  #include <conio.h>
  24236.  #include <math.h>
  24237.  #include <dos.h>
  24238.  
  24239.  void foo (void);
  24240.  void interrupt far myint (void);
  24241.  void main (void);
  24242.  
  24243.  /* Change the next line of code to "double a = 10.0"
  24244.     and the problem will go away. */
  24245.  float a = (float) 10.0;
  24246.  
  24247.  void foo (void)
  24248.     {
  24249.     cprintf("The sqrt of %lf is %lf.\n\r",(double) a,sqrt((double) a));
  24250.     }
  24251.  
  24252.  void interrupt far myint (void)
  24253.     {
  24254.     foo();
  24255.     }
  24256.  
  24257.  void main (void)
  24258.     {
  24259.     foo();
  24260.     _dos_setvect (0x65, myint);
  24261.     _dos_keep (0, 2000);
  24262.     }
  24263.  
  24264.  The above program is a TSR interrupt handler for INT 65h, which prints
  24265.  out the values 10.0 and sqrt(10.0) to the console when invoked. To see
  24266.  the problem with the above program, follow these steps:
  24267.  
  24268.  1. Compile with the large memory model (/AL), and run.
  24269.  
  24270.  2. Invoke interrupt 65h through the DOS DEBUG.EXE utility, as follows:
  24271.  
  24272.     a. debug  Press ENTER.
  24273.  
  24274.     b. a      Press ENTER.
  24275.  
  24276.     c. int 65 Press ENTER.
  24277.  
  24278.     d. ret    Press ENTER.
  24279.  
  24280.     e. Press ENTER.
  24281.  
  24282.     f. g      Press ENTER.
  24283.  
  24284.     g. q      Press ENTER.
  24285.  
  24286.  The problem disappears if you change the variable "a" from type
  24287.  "float" to type "double".
  24288.  
  24289.  
  24290.  535. Exemod Shows Min Alloc Greater Than Max Alloc with Link /CP:1
  24291.  
  24292.  Product Version(s): 5.10   | 5.10
  24293.  Operating System:   MS-DOS | OS/2
  24294.  Flags: ENDUSER | cvpack
  24295.  Last Modified: 15-JAN-1990    ArticleIdent: Q57607
  24296.  
  24297.  Problem:
  24298.  
  24299.  Looking at the header of a .EXE file, compiled with C Version 5.10
  24300.  with the following
  24301.  
  24302.     cl foo.c
  24303.  
  24304.  and linked with
  24305.  
  24306.     link /CP:1 /E foo;
  24307.  
  24308.  EXEMOD shows that the value of the minimum allocation(para) is higher
  24309.  than the value for maximum allocation(para).
  24310.  
  24311.  The description of EXEMOD implies that this is not possible (Page 323
  24312.  of the Microsoft "CodeView and Utilities, Microsoft Editor,
  24313.  Mixed-Language Programming Guide" manual, under the description of
  24314.  /MAX).
  24315.  
  24316.  Response:
  24317.  
  24318.  Under normal circumstances, the minimum allocation size cannot be
  24319.  larger than the maximum allocation size. However, on Page 324 of the
  24320.  Microsoft "CodeView and Utilities, Microsoft Editor, Mixed-Language
  24321.  Programming Guide" manual, it states the following:
  24322.  
  24323.     If either the /MIN or the /STACK option is used, the value is
  24324.     CORRECTED as necessary to accommodate unpacking of the modified
  24325.     stack. The /MAX option operates as it would for unpacked files.
  24326.  
  24327.  In other words, the minimum allocation value listed in a packed file
  24328.  is corrected to allow for the unpacked stack space. Since the maximum
  24329.  allocated value does not change for packed files, this COULD result in
  24330.  the minimum value being much larger than the maximum value. Note that
  24331.  this is the same whether the file is packed using the /E switch with
  24332.  LINK, or separately with EXEPACK.
  24333.  
  24334.  
  24335.  536. Example of Older FORTRAN Main to Newer C Procedure Call
  24336.  
  24337.  Product Version(s): 5.10   | 5.10
  24338.  Operating System:   MS-DOS | OS/2
  24339.  Flags: ENDUSER | H_FORTRAN 4.00
  24340.  Last Modified: 21-JAN-1990    ArticleIdent: Q57652
  24341.  
  24342.  When you link a mixed-language program, you must specify the newer
  24343.  version of the run-time library before the earlier version library on
  24344.  the link line, even if the earlier version of the library belongs to
  24345.  the main procedure in a mixed-language call.
  24346.  
  24347.  The following code is an example of a mixed-language program that uses
  24348.  a FORTRAN main program to call a C procedure to handle the graphics
  24349.  for the program. The code is intended to demonstrate correct compile
  24350.  and link switches when a FORTRAN routine is compiled with an earlier
  24351.  version of the FORTRAN package, which calls a C routine compiled with
  24352.  a newer version of the C package.
  24353.  
  24354.  The code begins execution in the FORTRAN main, then calls the C
  24355.  routine to handle elementary graphics routines. Notice the order of
  24356.  libraries specified on the link line.
  24357.  
  24358.  C*****************  FORMOD.FOR *****************
  24359.  C  FORMOD.FOR - FORTRAN 4.0 module to be used with CGRAPH
  24360.  
  24361.         INTERFACE TO SUBROUTINE CGRAPH[C, ALIAS:'_cgraph']
  24362.         END
  24363.  
  24364.         PROGRAM FORMOD
  24365.         CALL CGRAPH
  24366.         END
  24367.  
  24368.  /******************  CGRAPH.C *****************    */
  24369.  /* CGRAPH.C - C Graphics module. Used with FORMOD. */
  24370.  
  24371.  #include <stdio.h>
  24372.  #include <graph.h>
  24373.  #include <conio.h>
  24374.  
  24375.  void cgraph(void)
  24376.  {
  24377.      int i;
  24378.  
  24379.      i = _setvideomode(_MRES16COLOR);
  24380.      printf("return = %d", i); /* check for failed return */
  24381.      getch();
  24382.      _setvideomode(_DEFAULTMODE);
  24383.  }
  24384.  
  24385.  # ****************** FORMOD.MAK ***********************
  24386.  
  24387.  formod.obj: formod.for
  24388.          fl /Od /Zi /c /AL formod.for
  24389.  
  24390.  cgraph.obj: cgraph.c
  24391.          cl /Od /Zi /W3 /c /AL cgraph.c
  24392.  
  24393.  formod.exe: cgraph.obj formod.obj
  24394.          link /CO /NOE /NOD
  24395.          formod cgraph,,,llibcer.lib+llibfore.lib+graphics.lib;
  24396.  
  24397.  Note: The C graphics calls will fail if the earlier libraries (in this
  24398.  case, the FORTRAN libraries) are specified first on the link line.
  24399.  This is expected, as you always want newer definitions of the repeated
  24400.  code linked into your EXE file.
  24401.  
  24402.  For more information about FORTRAN and C mixed-language programming,
  24403.  see the "Mixed-Language Programming Guide" in your compiler
  24404.  documentation.
  24405.  
  24406.  
  24407.  537. Converting PL/M-386 Code to MSC
  24408.  
  24409.  Product Version(s): 5.10   | 5.10
  24410.  Operating System:   MS-DOS | OS/2
  24411.  Flags: ENDUSER |
  24412.  Last Modified: 12-FEB-1990    ArticleIdent: Q57748
  24413.  
  24414.  Microsoft does not make any PL/M conversion programs or utilities, nor
  24415.  do we know of any products for converting PL/M to C or MASM code that
  24416.  are explicitly compatible with Windows development. There are,
  24417.  however, several third-party vendor products (seen on a December 1988
  24418.  bulletin board).
  24419.  
  24420.  Microsoft has not tested these products, and therefore, we make no
  24421.  guarantees about them. You may want to contact the respective vendors
  24422.  for more information.
  24423.  
  24424.     Product: PL/M to C
  24425.     Korzeniewski: Frank Korzeniewski Consulting
  24426.     1564-A Fitzgeral Dr. #137
  24427.     Pinole, CA  94564
  24428.     (415) 799-1819
  24429.  
  24430.     Product: name not listed
  24431.     Lexeme Co.
  24432.     Richard Cox
  24433.     4 Station Square #250
  24434.     Commerce Court
  24435.     Pittsburg, PA  15219-1119
  24436.     (412) 281-5454
  24437.  
  24438.  Another less convenient possibility is to use CodeView (CV) to view
  24439.  the assembly code from the PL/M .EXE files. CV may be able to detect
  24440.  PUBLIC symbols, such as _main in Microsoft C or Pascal, which would
  24441.  allow you to skip start-up code and perhaps to keep track of where you
  24442.  are in your code. This will not result in complete or correct
  24443.  assembler, but it may ease the conversion process.
  24444.  
  24445.  You can use PRINT SCREEN to print the assembly code in 17 line blocks.
  24446.  Or you can invoke CodeView in sequential mode (/t), redirect to a
  24447.  file, and unassemble (U). For details, query on the following words:
  24448.  
  24449.     disassemble and codeview and listing
  24450.  
  24451.  
  24452.  538. Return Value for getch() on Extended Characters
  24453.  
  24454.  Product Version(s): 5.10   | 5.10
  24455.  Operating System:   MS-DOS | OS/2
  24456.  Flags: ENDUSER |
  24457.  Last Modified: 22-JAN-1990    ArticleIdent: Q57888
  24458.  
  24459.  When reading extended characters, you must make two calls to getch()
  24460.  because the first call returns a value indicating that the key is an
  24461.  extended character. The second call returns the actual key code. This
  24462.  is how extended keys are detected.
  24463.  
  24464.  When you are reading an extended character, the first return value
  24465.  will be either 0xE0 or 0x00, depending on which extended key is
  24466.  pressed.
  24467.  
  24468.  Sample Program
  24469.  --------------
  24470.  
  24471.  #include <stdio.h>
  24472.  #include <conio.h>
  24473.  void main(void)
  24474.  {
  24475.      int ch, scan;
  24476.  
  24477.      do {
  24478.          ch = getch();    /* 1st getch() gets ASCII code */
  24479.          printf("Character is %d\n", ch);
  24480.          if (ch == 0x00 || 0XE0)  { /* if extended key */
  24481.              scan = getch();  /* 2nd getch() gets "scan code" */
  24482.              printf("\tExtended character:  scan is %d\n", scan);
  24483.          }
  24484.      }  while (ch != 27);    /* exit loop on ESC */
  24485.  }
  24486.  
  24487.  For a discussion of keystrokes and scan codes, refer to "The New Peter
  24488.  Norton Programmer's Guide to the IBM PC & PS/2," Pages 128 to 130.
  24489.  
  24490.  
  24491.  539. File Buffering Can Hide Out-of-Disk-Space Condition
  24492.  
  24493.  Product Version(s): 5.10   | 5.10
  24494.  Operating System:   MS-DOS | OS/2
  24495.  Flags: ENDUSER | s_quickc s_quickasm
  24496.  Last Modified: 22-JAN-1990    ArticleIdent: Q57889
  24497.  
  24498.  If disk space is exceeded, file buffering fails when buffering is done
  24499.  by the stream I/O functions. For example, if a file buffer for a
  24500.  stream is set to 10K by setvbuf() but only 2K disk space is available,
  24501.  all data written to the buffer above 2K will be lost. This problem can
  24502.  occur even when setvbuf() and fwrite() return successful return codes.
  24503.  
  24504.  In the case where there is less space on the disk than there is in the
  24505.  stream buffer, all stream I/O functions will seem to work properly
  24506.  until the stream buffer is filled [for example, fwrite() returns the
  24507.  number of bytes written as if it were successful]. However, the status
  24508.  of these functions is valid only for the data going to the buffer and
  24509.  is not reflected in the file that is written to the disk.
  24510.  
  24511.  The problem is due to the existence of both the C run-time buffers and
  24512.  the DOS buffers. Only when the DOS buffers try to write to disk does
  24513.  it become evident that the disk is full. Then, the next return value
  24514.  from fwrite() will indicate failure.
  24515.  
  24516.  The following is the series of events that leads to the loss of data
  24517.  with buffered stream I/O functions:
  24518.  
  24519.  1. The stream is opened with fopen().
  24520.  
  24521.  2. Buffering is set on the stream, either 512 bytes default or the number
  24522.     of bytes selected by the user with setvbuf().
  24523.  
  24524.  3. There is less disk space than the size of the buffer set by Step 2.
  24525.  
  24526.  4. Bytes are written to the file [for example, fwrite()], with
  24527.     successful return codes.
  24528.  
  24529.  5. The buffer is filled and then the stream I/O function attempts to
  24530.     write all data to DOS.
  24531.  
  24532.  6. The bytes that can fit on the disk are written and all remaining
  24533.     data that was in the buffer is lost.
  24534.  
  24535.  7. Successive calls to write data to the file fail.
  24536.  
  24537.  The following are possible workarounds:
  24538.  
  24539.  1. Turn buffering off by setting the file buffer to NULL, using
  24540.     setvbuf().
  24541.  
  24542.  2. Use nonbuffered I/O functions, such as open(), read(), and write().
  24543.  
  24544.  3. Check the result of closing the stream with fclose(), which flushes
  24545.     all buffers associated with the given stream prior to closing.
  24546.  
  24547.  4. Set buffering to the same size as the records that are being
  24548.     written. The third workaround will force fwrite() to return a
  24549.     "failure" return code at a point where the program can easily
  24550.     recover because the program knows exactly which records were
  24551.     successfully written to disk and which one was not.
  24552.  
  24553.  
  24554.  540. "UNKNOWN WARNING" May Result from Bad Error Message File
  24555.  
  24556.  Product Version(s): 5.10   | 5.10
  24557.  Operating System:   MS-DOS | OS/2
  24558.  Flags: ENDUSER |
  24559.  Last Modified:  8-MAR-1990    ArticleIdent: Q57942
  24560.  
  24561.  If a number of compiler warning messages contain the description
  24562.  "UNKNOWN WARNING", the cause may be the use of an incorrect or
  24563.  corrupted error message file. The compiler generates the correct error
  24564.  number, but since the messages are retrieved from a separate file, the
  24565.  compiler displays "UNKNOWN WARNING" when it cannot find a match.
  24566.  
  24567.  The error message files for C 5.10 should contain messages for all
  24568.  errors and warnings generated. If you look up the number of a compiler
  24569.  error in the documentation and find a normally documented error, then
  24570.  you should be suspicious of your .ERR error message files.
  24571.  
  24572.  The simplest check is to reinstall the error message files from the
  24573.  original C 5.10 disks and then recompile to see if the error messages
  24574.  appear correctly. The .ERR files to recopy are CL.ERR and C23.ERR from
  24575.  the Setup disk and C1.ERR from the disk labeled Compiler Disk 1.
  24576.  
  24577.  
  24578.  541. Err Msg: C1064 Too Many _text Segments
  24579.  
  24580.  Product Version(s): 5.10   | 5.10
  24581.  Operating System:   MS-DOS | OS/2
  24582.  Flags: ENDUSER |
  24583.  Last Modified: 25-JUL-1990    ArticleIdent: Q58522
  24584.  
  24585.  Question:
  24586.  
  24587.  When I compile my program, I get a fatal error message "C1064 : too
  24588.  many _text segments". What is wrong?
  24589.  
  24590.  Response:
  24591.  
  24592.  This error is caused by using the alloc_text pragma to define more
  24593.  than 10 distinct _text segments in a single "compilation unit". The
  24594.  following code reproduces the error message:
  24595.  
  24596.  Sample Code
  24597.  -----------
  24598.  
  24599.  /*******************************/
  24600.  /* Define _text segments here. */
  24601.  /*******************************/
  24602.  
  24603.  #pragma alloc_text(foo_1,foofunct_1)
  24604.  #pragma alloc_text(foo_2,foofunct_2)
  24605.      .
  24606.      .
  24607.      .
  24608.  #pragma alloc_text(foo_11,foofunct_11)
  24609.  
  24610.  /*******************************/
  24611.  /* Define Prototypes           */
  24612.  /*******************************/
  24613.  
  24614.  void main(void);
  24615.  void foofunct_1(void);
  24616.  void foofunct_2(void);
  24617.      .
  24618.      .
  24619.      .
  24620.  void foofunct_11(void);
  24621.  
  24622.  /********************/
  24623.  /* Define functions */
  24624.  /********************/
  24625.  
  24626.  void main(void)
  24627.  {
  24628.     printf("Here we go. Eleven alloc_text pragmas: \n");
  24629.  }
  24630.  
  24631.  void foofunct_1(void)
  24632.  {
  24633.  }
  24634.  void foofunct_2(void)
  24635.  {
  24636.  }
  24637.      .
  24638.      .
  24639.      .
  24640.  void foofunct_11(void)
  24641.  {
  24642.  }
  24643.  
  24644.  See the "Microsoft C Optimizing Compiler: User's Guide" Version 5.1
  24645.  manual. The alloc_test pragma is detailed on Page 159. The error
  24646.  message (C1064) is documented in the "Microsoft C for MS-DOS and OS/2
  24647.  Operating Systems: Version 5.1 Update" on Page 59.
  24648.  
  24649.  
  24650.  542. Escape Character Erases First Characters in gets() String
  24651.  
  24652.  Product Version(s): 5.00 5.10 | 5.10
  24653.  Operating System:   MS-DOS    | OS/2
  24654.  Flags: ENDUSER | s_quickc s_quickasm 1.00 1.01 2.00 2.01
  24655.  Last Modified: 26-JAN-1990    ArticleIdent: Q57948
  24656.  
  24657.  If you enter the escape character (ASCII 1Bh) from the keyboard
  24658.  (console) into a string that gets(), cgets(), or fgets() is reading,
  24659.  all of the string previously read in is erased. The string pointer is
  24660.  reset so that characters following the escape character are read into
  24661.  the beginning of the string. This is consistent with the action done
  24662.  by the operating system (OS) to parse the input-line.
  24663.  
  24664.  However, if the escape character is input from a file by redirection,
  24665.  the entire string including the escape character will be read into the
  24666.  string.
  24667.  
  24668.  Code Example
  24669.  ------------
  24670.  
  24671.  #include <conio.h>
  24672.  #include <stdio.h>
  24673.  
  24674.  char buf[22];
  24675.  char *result;
  24676.  
  24677.  void main(void)
  24678.  {
  24679.       int i;
  24680.       buf[0] = 20;
  24681.  
  24682.       printf("Enter your text: \n");
  24683.       result = gets(buf);
  24684.  
  24685.       printf ( "Resulting String: %s\n", result );
  24686.       for( i = 0; i < 20; i ++ )
  24687.       {
  24688.            printf("Buf[%2d] = %c (char)\n", i, buf[i]);
  24689.       }
  24690.  }
  24691.  
  24692.  Enter the following string as a test:
  24693.  
  24694.     abcdef<esc>ghijk
  24695.  
  24696.  Note that the resulting string is output as:
  24697.  
  24698.     ghijk
  24699.  
  24700.  Now, using a text editor that will accept an escape character embedded
  24701.  in a string, create a data file with the same string. If the above
  24702.  program is run with input redirected from the data file, for example
  24703.  
  24704.     program <test.dat
  24705.  
  24706.  the resulting string is output as follows:
  24707.  
  24708.     abcdef<esc>ghijk
  24709.  
  24710.  This behavior occurs in the entire gets() family of routines,
  24711.  including gets(), cgets(), and fgets(). If the input is coming from
  24712.  the console, the run time will use the standard MS-DOS OS/2 keyboard
  24713.  read routines. On the other hand, if the input is coming from a file
  24714.  (through redirection) there is no editing performed by the OS and the
  24715.  file is read in literally.
  24716.  
  24717.  
  24718.  543. Use of the Stringizing Operator (#) in Macros
  24719.  
  24720.  Product Version(s): 3.x 4.x 5.00 5.10 | 5.10
  24721.  Operating System:   MS-DOS            | OS/2
  24722.  Flags: ENDUSER | s_quickc s_quickasm 1.x 2.00 2.01
  24723.  Last Modified:  7-MAR-1990    ArticleIdent: Q57949
  24724.  
  24725.  When you are writing a preprocessor macro that takes an argument that
  24726.  must appear in quotation marks, you can use the # sign to expand the
  24727.  argument. One implementation of this preprocessor directive is the use
  24728.  of printf() in the macro. The following code demonstrates an example:
  24729.  
  24730.  Code Example
  24731.  ------------
  24732.  
  24733.  #define PR(fmt,value) printf("value = %" #fmt "\n", (value))
  24734.  
  24735.  #include <stdio.h>
  24736.  
  24737.  void main(void)
  24738.  {
  24739.     float afl;
  24740.  
  24741.     afl = 3.14f;
  24742.     PR(5.2f, afl);
  24743.  }
  24744.  
  24745.  The sample code outputs the following string:
  24746.  
  24747.     value =  3.14
  24748.  
  24749.  The # sign in front of the fmt variable allows the macro to be
  24750.  expanded out with quotation marks. Note that the preprocessor
  24751.  concatenates consecutive pairs of double quotation marks so that the
  24752.  following string
  24753.  
  24754.     "value = %""5.2f""\n"
  24755.  
  24756.  is translated into the following:
  24757.  
  24758.     "value = %5.2f\n"
  24759.  
  24760.  
  24761.  544. Why External References Are Created When They're Not Needed
  24762.  
  24763.  Product Version(s): 5.00 5.10 | 5.10
  24764.  Operating System:   MS-DOS    | OS/2
  24765.  Flags: ENDUSER |
  24766.  Last Modified: 15-MAY-1990    ArticleIdent: Q57961
  24767.  
  24768.  Problem:
  24769.  
  24770.  In the following example, Microsoft C compiler versions 5.00 and 5.10
  24771.  generate an extern reference to printf(); therefore, the function is
  24772.  included at link time. This apparently is a bug since the compiler
  24773.  correctly ignores generating any code for the "if" statement.
  24774.  
  24775.  The following is code example:
  24776.  
  24777.  #define VERBOSE 0
  24778.  
  24779.  int  function(void)
  24780.  {
  24781.    if (VERBOSE) printf("hello world\n");
  24782.  
  24783.    return 1;
  24784.  }
  24785.  
  24786.  Response:
  24787.  
  24788.  The way it works now is by design. The extern reference is generated
  24789.  in the first pass of the compiler and the "if" code is removed in pass
  24790.  two. Furthermore, according to ANSI specifications (Section 3.7,
  24791.  "External Definitions" in December 7, 1988 draft), the extern is
  24792.  required.
  24793.  
  24794.  If your purpose is to provide conditional code for debugging reasons,
  24795.  the preprocessor is much better suited to the task.
  24796.  
  24797.  The above code fragment should be changed to the following:
  24798.  
  24799.  #define VERBOSE 0
  24800.  
  24801.  int  function(void)
  24802.  {
  24803.  #if (VERBOSE)
  24804.    printf("hello world\n");
  24805.  #endif
  24806.  
  24807.    return 1;
  24808.  }
  24809.  
  24810.  
  24811.  545. Unresolved Externals from GRAPHICS.LIB
  24812.  
  24813.  Product Version(s): 5.10
  24814.  Operating System:   MS-DOS
  24815.  Flags: ENDUSER | s_quickc s_quickasm
  24816.  Last Modified: 26-JAN-1990    ArticleIdent: Q57971
  24817.  
  24818.  When linking a program with a version of GRAPHICS.LIB newer than the
  24819.  one supplied with your compiler, the following unresolved externals
  24820.  will occur:
  24821.  
  24822.     LINK : error L2029: Unresolved externals:
  24823.  
  24824.     __aDBdoswp in file(s):
  24825.      d:\lib\GRAPHICS.LIB(..\gr\qcswap.asm)
  24826.     ___aDBswpchk in file(s):
  24827.      d:\lib\GRAPHICS.LIB(..\gr\qcswap.asm)
  24828.     ___aDBswpflg in file(s):
  24829.      d:\lib\GRAPHICS.LIB(..\gr\qcswap.asm)
  24830.  
  24831.     There were 3 errors detected
  24832.  
  24833.  Code Example
  24834.  ------------
  24835.  
  24836.  #include <stdio.h>
  24837.  #include <graph.h>
  24838.  
  24839.  void main(void)
  24840.  {
  24841.      _clearscreen ( _GCLEARSCREEN );
  24842.      _settextcolor ( 1L );
  24843.      _outtext ("Hello");
  24844.      getch();
  24845.  }
  24846.  
  24847.  Following are the steps to re-create the unresolved externals:
  24848.  
  24849.  1. Compile the program using Microsoft C 5.10 compiler and link the
  24850.     object file with GRAPHICS.LIB from either FORTRAN 5.00, QuickC
  24851.     2.00, or QuickC 2.01.
  24852.  
  24853.  2. Compile the program using Microsoft QuickC 2.00 or 2.01 and link
  24854.     the object file with GRAPHICS.LIB from FORTRAN 5.00.
  24855.  
  24856.  To determine which GRAPHICS.LIB came with which package, check the
  24857.  size of the GRAPHICS.LIB file (shown below):
  24858.  
  24859.     C 5.10                       - 59357 bytes   3-07-88   5:10a
  24860.  
  24861.     QuickC 2.00                  - 75337 bytes  12-13-88  10:19a
  24862.  
  24863.     QuickC w/QuickAssembler 2.01 - 75871 bytes   3-08-89  11:17a
  24864.  
  24865.     FORTRAN 5.00                 - 76467 bytes   3-24-89   8:56p
  24866.  
  24867.  It is recommended that you use the version of GRAPHICS.LIB that comes
  24868.  with the compiler to avoid any problems.
  24869.  
  24870.  
  24871.  546. C2144 May Be Caused by Executable Code Between Declarations
  24872.  
  24873.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  24874.  Operating System:   MS-DOS              | OS/2
  24875.  Flags: ENDUSER | s_quickc s_quickasm
  24876.  Last Modified: 12-FEB-1990    ArticleIdent: Q58559
  24877.  
  24878.  Compiler Error C2144 is defined as follows:
  24879.  
  24880.     syntax error : missing 'token' before type 'type'
  24881.  
  24882.  You may receive this error message if your program places executable
  24883.  code before a data declaration, a practice which was acceptable in
  24884.  Kernighan and Ritchie C, but has since been outlawed in later versions
  24885.  of the ANSI drafts.
  24886.  
  24887.  This error message will normally occur if a required closing curly
  24888.  brace (}), right parenthesis [)], or semicolon (;) is missing.
  24889.  
  24890.  The following code demonstrates this error message:
  24891.  
  24892.  /* Program : foo.c */
  24893.  
  24894.  #include <stdio.h>
  24895.  
  24896.  void main(void)
  24897.  {
  24898.          int i;
  24899.          printf("Beetlejuice\n");
  24900.          int j;
  24901.  }
  24902.  
  24903.  Compiling this code with Microsoft C Version 3.00, 4.00, 5.00, or
  24904.  5.10, or QuickC Version 1.00, 1.01, 2.00, or 2.01 will return the
  24905.  following error message:
  24906.  
  24907.     foo.c
  24908.     foo.c(7) : error C2144: syntax error : missing ';' before
  24909.             type 'int'
  24910.  
  24911.  Placing all data declarations before all executable code corrects the
  24912.  programming error.
  24913.  
  24914.  
  24915.  547. Changing a Drive's Volume Label
  24916.  
  24917.  Product Version(s): 5.10
  24918.  Operating System:   MS-DOS
  24919.  Flags: ENDUSER | s_quickc s_quickasm h_masm
  24920.  Last Modified: 14-MAR-1990    ArticleIdent: Q58650
  24921.  
  24922.  Changing a drive's volume label involves the use of FCB (File Control
  24923.  Block) file processing, and therefore, is not supplied with the C
  24924.  run-time libraries. However, one of the ways to do this is through DOS
  24925.  int 21h calls for FCB file manipulation.
  24926.  
  24927.  Below is an assembly routine written with Microsoft MASM Version 5.10
  24928.  to change a drive's volume name. To do this, it first sets up an
  24929.  extended FCB to allow for manipulating files with attributes. Offset 6
  24930.  of the FCB is set to 8 (_A_VOLID defined in dos.h) to specify a
  24931.  volume. The old volume is searched for with "*.*" as a pattern and
  24932.  deleted, then the volume is re-created with the new volume label
  24933.  passed by the C caller. The function returns the error code supplied
  24934.  from the DOS API that creates the volume label.
  24935.  
  24936.  Use the following:
  24937.  
  24938.   rc = NewVol( iDrive, szName ); // iDrive = Drive number ( 1, 2, ... )
  24939.                                 // szName = Up to 11 chars. DOS filename
  24940.                                 // rc = Return Code from function.
  24941.  
  24942.  The new volume label must be passed with 11 characters for the name.
  24943.  Anything less MUST be padded with spaces.
  24944.  
  24945.  Sample Code
  24946.  -----------
  24947.  
  24948.  ;   unsigned NewVol( int, char * ) will delete a disk volume and
  24949.  ;                                  create one with the new name.
  24950.  ;
  24951.  ; Assemble with /Dmodel={SMALL MEDIUM COMPACT LARGE}
  24952.  ;               /Dlang={C FORTRAN BASIC PASCAL}
  24953.  
  24954.  %.MODEL model,lang
  24955.  
  24956.  .DATA
  24957.  maxlen  EQU     11                 ;Maximum name length
  24958.  datasz  EQU      2                 ;Size of Data Pointers
  24959.  ;   Setup an extended FCB
  24960.  fcb     DB      255, 0, 0, 0, 0, 0, 8, 1
  24961.          DB      37 DUP (?)
  24962.  default DB      '*       *  '      ;Equivalent to "*.*"
  24963.  
  24964.  .CODE
  24965.  NewVol  PROC USES si di es, Drive:WORD, VolName:WORD
  24966.          mov     bx,Drive           ;Get drive number ( 1 byte )
  24967.          mov     fcb+7,bl           ;...and store in FCB offset 7
  24968.          mov     ax,ds
  24969.          mov     es,ax
  24970.          cld                        ;Upward move
  24971.          mov     cx,maxlen          ;Size of move
  24972.          mov     si,OFFSET default  ;Source string to
  24973.          mov     di,OFFSET fcb+8    ;...filename offset in 8 FCB
  24974.          rep     movsb              ;Move maxlen bytes of vol name
  24975.          mov     dx,OFFSET fcb      ;Delete volume off drive
  24976.          mov     ah,13H
  24977.          int     21H
  24978.          mov     cx,maxlen
  24979.          mov     si,VolName         ;New name passed by C caller
  24980.          mov     di,OFFSET fcb+8
  24981.          rep     movsb              ;Copy 11 chars for new label
  24982.          mov     dx,OFFSET fcb      ;Create the new volume
  24983.          mov     ah,16H
  24984.          int     21H
  24985.          mov     dx,OFFSET fcb      ;Close the file
  24986.          mov     ah,10H
  24987.          int     21H
  24988.          mov     ah,0
  24989.          ret
  24990.  NewVol  ENDP
  24991.          END
  24992.  
  24993.  
  24994.  548. Redirecting stdout to and from a File Using C
  24995.  
  24996.  Product Version(s): 5.00 5.10  | 5.10
  24997.  Operating System:   MS-DOS     | OS/2
  24998.  Flags: ENDUSER | s_quickc
  24999.  Last Modified: 26-FEB-1990    ArticleIdent: Q58667
  25000.  
  25001.  Question:
  25002.  
  25003.  How do I redirect stdout to a file from a C program, then get the
  25004.  original stdout back at a later time in the same program?
  25005.  
  25006.  Response:
  25007.  
  25008.  The C function typically used to redirect stdout or stdin is
  25009.  freopen(). To redirect stdout to a file called FOO.TXT, use the
  25010.  following call:
  25011.  
  25012.     freopen( "foo.txt", "w", stdout );
  25013.  
  25014.  This statement causes all subsequent output, which is typically
  25015.  directed towards stdout, to go to the file FOO.TXT.
  25016.  
  25017.  To get stdout back to the keyboard (the default stdout), use the
  25018.  following call:
  25019.  
  25020.     freopen( "CON", "w", stdout );
  25021.  
  25022.  In both of these cases, check the return value of freopen() to make
  25023.  sure that the redirection actually took place.
  25024.  
  25025.  Below is a short program to demonstrate the redirection of stdout:
  25026.  
  25027.  #include <stdio.h>
  25028.  #include <stdlib.h>
  25029.  
  25030.  void main(void)
  25031.  {
  25032.     FILE *stream ;
  25033.  
  25034.     if((stream = freopen("foo.txt", "w", stdout)) == NULL)
  25035.        exit(-1);
  25036.  
  25037.     printf("this is stdout output\n");
  25038.  
  25039.     stream = freopen("CON", "w", stdout);
  25040.  
  25041.     printf("And now back to the console once again\n");
  25042.  }
  25043.  
  25044.  This program assumes that stdout is to be redirected toward the
  25045.  console at the end of the program.
  25046.  
  25047.  
  25048.  549. Using _dos_findfirst() Function to Retrieve Disk Volume
  25049.  
  25050.  Product Version(s): 5.10
  25051.  Operating System:   MS-DOS
  25052.  Flags: ENDUSER | s_quickc 2.00 s_quickasm 2.01
  25053.  Last Modified: 26-FEB-1990    ArticleIdent: Q58800
  25054.  
  25055.  Question:
  25056.  
  25057.  I am using the _dos_findfirst() function to find my disk volume. I use
  25058.  the _A_VOLID attribute to get the disk volume and it works correctly,
  25059.  except when I get a volume name greater than eight characters. Then, I
  25060.  get a period embedded in the middle of my string. For example, if my
  25061.  volume name is "VOLUMENAME", _dos_findfirst returns "VOLUMENA.ME". Why
  25062.  does the period get embedded in the string?
  25063.  
  25064.  Response:
  25065.  
  25066.  Volume labels are a specific type of directory entry specified by
  25067.  setting bit 3 in the attribute field to 1 or 0x08. They are a special
  25068.  type of file that can only be in the root directory. The maximum
  25069.  number of characters a volume label can have is 11 characters (8
  25070.  characters for the filename followed by a three-character extension).
  25071.  
  25072.  The C run-time function _dos_findfirst() will return the volume label
  25073.  in a file format since DOS stores the volume label in the file format.
  25074.  
  25075.  
  25076.  550. Cannot Allocate More Than 64K with Calloc()
  25077.  
  25078.  Product Version(s): 5.10   | 5.10
  25079.  Operating System:   MS-DOS | OS/2
  25080.  Flags: ENDUSER | s_quickc s_quickasm
  25081.  Last Modified:  8-MAR-1990    ArticleIdent: Q58933
  25082.  
  25083.  Although calloc() takes two unsigned integers as parameters, it does
  25084.  not allocate more than 64K. Calloc() determines the size you are
  25085.  attempting to allocate by multiplying the two arguments. If the size
  25086.  is greater than 64K, it will return NULL.
  25087.  
  25088.  The confusion typically arises because, with malloc(), it is
  25089.  impossible to ask for more than 64K due to the size of the argument
  25090.  malloc() takes. Malloc() takes an unsigned int as an argument;
  25091.  therefore, the largest number you can pass it cannot be greater than
  25092.  64K. This is not the case with calloc() -- so one might make the
  25093.  assumption that you COULD allocate more than 64K with calloc(). This
  25094.  is simply not the case.
  25095.  
  25096.  
  25097.  551. If .DLL Is Linked with CRTLIB, Then .EXE Must Be Linked, Too
  25098.  
  25099.  Product Version(s): 5.10
  25100.  Operating System:   OS/2
  25101.  Flags: ENDUSER |
  25102.  Last Modified:  6-MAR-1990    ArticleIdent: Q58961
  25103.  
  25104.  When you write a program that uses a DLL that has been linked with
  25105.  CRTLIB.DLL, then the program itself must also link with CRTLIB.DLL.
  25106.  The diagram and text in Section 5.2 of MTDYNA.DOC explain this close
  25107.  relationship in detail.
  25108.  
  25109.  Also in MTDYNA.DOC, the table in Section 6 is very useful for
  25110.  identifying which components to use for which type of output file
  25111.  (.EXE or .DLL). The following is a diagram of the library
  25112.  relationships in the table:
  25113.  
  25114.                 +---------+       |                    +---------+
  25115.             /   | xLIBCyP |       |                /   | LLIBCDLL|
  25116.         single  +---------+       |            single  +---------+
  25117.  +-----+/  thread                 |     +-----+/  thread
  25118.  | EXE |                          |     | DLL |
  25119.  +-\---+\                         |     +-----+\
  25120.    multiple                       |           multiple
  25121.      thread     +---------+       |             thread +---------+
  25122.       \      \  | LLIBCMT |       |                \   | CRTLIB  |
  25123.        \ (or)   +---------+       |                    +---------+
  25124.         \ ________________________________________________/
  25125.  
  25126.  As long as the .EXE is independent of any DLLs, it links with either
  25127.  xLIBCyP.LIB or LLIBCMT.LIB, depending on whether the .EXE is single or
  25128.  multithreaded. When the .EXE uses a DLL, the .EXE links with either
  25129.  xLIBCyP.LIB or CRTLIB.LIB, depending on whether the DLL is single or
  25130.  multithreaded.
  25131.  
  25132.  Additional .OBJs and .LIBs are linked for multithreaded .EXEs and for
  25133.  single and multithreaded DLLs. You can find complete detailed
  25134.  information about compiling and linking multithreaded programs and
  25135.  dynamic link libraries in MTDYNA.DOC, which is provided on the C 5.10
  25136.  disks.
  25137.  
  25138.  For further information, query on the following words:
  25139.  
  25140.     CRTLIB and DLL
  25141.  
  25142.  
  25143.  552. Pointer Arithmetic Wraps Around Segment Ends
  25144.  
  25145.  Product Version(s): 5.10   | 5.10
  25146.  Operating System:   MS-DOS | OS/2
  25147.  Flags: ENDUSER |
  25148.  Last Modified:  1-MAR-1990    ArticleIdent: Q58987
  25149.  
  25150.  When you increment or decrement a pointer beyond a segment boundary,
  25151.  the offset of the pointer will wrap around the end. For example, if
  25152.  the pointer is sitting at FFFF and you increment it by 1 (one), the
  25153.  resulting value of the offset is 0000. This wraparound behavior is
  25154.  expected behavior in all memory models except huge. The example below
  25155.  demonstrates the "hidden" wraparound.
  25156.  
  25157.  The C language permits writing beyond array boundaries and heap
  25158.  allocations. Consequently, C compilers do not generate warning or
  25159.  error messages if an index or pointer goes out of bounds. It is up to
  25160.  the programmer to monitor indices and pointers.
  25161.  
  25162.  If you have an array that is larger than 64K, use the huge keyword or
  25163.  compile in the huge memory model. Pointer arithmetic for huge data is
  25164.  performed on the full 32 bits of segment and offset address. For
  25165.  complete information on huge model programming, refer to Chapter 6 in
  25166.  the "Microsoft C Optimizing Compiler User's Guide."
  25167.  
  25168.  Sample Code:
  25169.  
  25170.  /* wrap.c */
  25171.  #include <stdio.h>
  25172.  #include <dos.h>
  25173.  #include <malloc.h>
  25174.  
  25175.  void main (void)
  25176.  {
  25177.   char *ptr;
  25178.  
  25179.   ptr = (char*) malloc (100);
  25180.   printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
  25181.  
  25182.   FP_OFF(ptr) = 0x0000;
  25183.   printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
  25184.   ptr--;
  25185.   printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
  25186.  
  25187.   FP_OFF(ptr) = 0xFFFF;
  25188.   printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
  25189.   ptr++;
  25190.   printf ("\nSegment is %u, offset is %u\n", FP_SEG(ptr), FP_OFF(ptr));
  25191.  }
  25192.  
  25193.  
  25194.  553. Buffer Size for fcvt, ecvt Is 349 Bytes
  25195.  
  25196.  Product Version(s): 5.10   | 5.10
  25197.  Operating System:   MS-DOS | OS/2
  25198.  Flags: ENDUSER | s_quickc s_quickasm
  25199.  Last Modified: 15-MAR-1990    ArticleIdent: Q59070
  25200.  
  25201.  Question:
  25202.  
  25203.  The run-time references to the ecvt and fcvt routines say that they
  25204.  use a single, statically allocated buffer while converting floating
  25205.  point numbers to character strings. How large is this buffer?
  25206.  
  25207.  Response:
  25208.  
  25209.  The buffer is currently defined as 349 bytes. However, the largest
  25210.  double-precision variable that can be used is 309 bytes, with 40 bytes
  25211.  for padding.
  25212.  
  25213.  Note: This size may change in future releases of Microsoft's C
  25214.  compilers, so you should not rely on the consistency of this size.
  25215.  
  25216.  
  25217.  
  25218.  554. Changing a Compaq's CPU Speed
  25219.  
  25220.  Product Version(s): 5.10
  25221.  Operating System:   MS-DOS
  25222.  Flags: ENDUSER | s_quickc s_quickasm
  25223.  Last Modified: 15-MAR-1990    ArticleIdent: Q59071
  25224.  
  25225.  There are no C run-time functions that change the CPU speed, but there
  25226.  is an interrupt that will change the speed of the CPU. This interrupt,
  25227.  shown below, works only on Compaq computers.
  25228.  
  25229.  INT 16h:
  25230.  
  25231.       AH = F0h
  25232.       AL = speed
  25233.            00h  equivalent to 6 MHz
  25234.            01h  equivalent to 8 MHz
  25235.            02h  full 16 MHz
  25236.            03h  toggles between 8 MHz -- equivalent and speed set by
  25237.                 system board switch (AUTO or HIGH)
  25238.            08h  full 16 MHz except 8 MHz during floppy disk access
  25239.            09h  specify speed directly
  25240.                 CX = speed value, 1 (slowest) to 50 (full), 3 ~= 8088
  25241.  
  25242.  To read the current CPU speed, set AH = F1h and call interrupt 16h.
  25243.  
  25244.  INT 16h:
  25245.       AH = F1h
  25246.  RETURN:
  25247.       AL = speed code (see function F0h for speed code)
  25248.            if AL = 09h, CX = speed code
  25249.  
  25250.  
  25251.  555. Determining Size of Memory Block Referenced by a Pointer
  25252.  
  25253.  Product Version(s): 5.00   | 5.10
  25254.  Operating System:   MS-DOS | OS/2
  25255.  Flags: ENDUSER | s_quickc s_quickasm
  25256.  Last Modified: 15-MAR-1990    ArticleIdent: Q59087
  25257.  
  25258.  Question:
  25259.  
  25260.  Is there a function in the Microsoft C run-time library that returns
  25261.  the amount of memory that has been allocated to a pointer by malloc()?
  25262.  If not, is there a way I can write my own?
  25263.  
  25264.  Response:
  25265.  
  25266.  There is no C run-time library function that explicitly returns the
  25267.  amount of memory that has been allocated to a pointer by malloc().
  25268.  However, it is possible to retrieve this information indirectly
  25269.  through the Microsoft C run-time library function _heapwalk(). The
  25270.  _heapwalk() function returns a heap information structure of the
  25271.  following form:
  25272.  
  25273.     struct _heapinfo {
  25274.         int far * _pentry;
  25275.         size_t _size;
  25276.         int _useflag;
  25277.     } _HEAPINFO;
  25278.  
  25279.  The information returned in this structure can be accessed directly or
  25280.  used in writing a function that gives the size information you want.
  25281.  The following is sample code:
  25282.  
  25283.  #include <stddef.h>
  25284.  #include <malloc.h>
  25285.  
  25286.  size_t msize(void * pointer, int * error)
  25287.  {
  25288.     struct _heapinfo info; /* Heap info structure */
  25289.     int   heap_status;     /* Heap status */
  25290.     size_t  ret_val;       /* msize() return value */
  25291.  
  25292.     info._pentry = NULL;   /* Initialize heap info structure */
  25293.  
  25294.     do {
  25295.        heap_status = _heapwalk(&info); /* Step through heap until */
  25296.     } while ((pointer != info._pentry) /* desired entry is found  */
  25297.       && (heap_status == _HEAPOK));   /* or a heap error occurs. */
  25298.  
  25299.     if(heap_status == _HEAPOK)
  25300.        if(info._useflag != _FREEENTRY)
  25301.           ret_val = info._size;          /* no errors */
  25302.        else {
  25303.           ret_val = -1;                  /* entry has been freed */
  25304.           *error = _FREEENTRY;
  25305.        }
  25306.     else {
  25307.        ret_val = -1;     /* a heap error occurred */
  25308.        *error = heap_status;
  25309.     }
  25310.     return(ret_val);
  25311.  }
  25312.  
  25313.  Note: The msize() function takes as a parameter a pointer pointing to
  25314.  the base memory that was allocated. For msize() to work correctly,
  25315.  this pointer MUST point to the base of the allocated block, and not
  25316.  anywhere within that block.
  25317.  
  25318.  The msize() function returns the size of the allocated block or -1 if
  25319.  an error occurs. If -1 is returned, an error code is returned through
  25320.  the error parameter. The error parameter will be one of the following
  25321.  manifest constants:
  25322.  
  25323.     _FREENTRY      _HEAPEMPTY      _HEAPBADPTR
  25324.     _HEAPBADBEGIN  _HEAPBADNODE    _HEAPEND
  25325.  
  25326.  These error codes are actually generated by the Microsoft run-time
  25327.  library function _heapwalk(). Refer to your Microsoft C Compiler's
  25328.  documentation on _heapwalk() for more information on the meaning of
  25329.  these error codes.
  25330.  
  25331.  Following is a sample program that uses of the msize() function to
  25332.  find the amount of memory allocated to a pointer. This function is
  25333.  designed to work in any memory model:
  25334.  
  25335.  #include <stdio.h>
  25336.  #include <malloc.h>
  25337.  
  25338.  size_t msize(void *, int *);
  25339.  
  25340.  void main (void)
  25341.  {
  25342.     char * p;
  25343.     int    error;
  25344.     size_t size;
  25345.  
  25346.     p = (char *)malloc(sizeof(char) * 11)
  25347.     if(p = NULL) {
  25348.        printf("Memory allocation error\n");
  25349.        return;
  25350.     }
  25351.  
  25352.     size = msize(p,&error);
  25353.     if(size == -1)
  25354.        printf("An msize error has occurred\n");
  25355.     else
  25356.        printf("Size = %u\n", size);
  25357.  }
  25358.  
  25359.  Note: The malloc() function allocates 11 bytes of memory for use by
  25360.  the pointer p. Surprisingly, msize() returns 12 as the size of the
  25361.  allocated block. Actually, this is an expected result. Malloc() always
  25362.  allocates even-byte amounts as a result of PC architecture.
  25363.  Consequently, msize()'s return value always is an even amount.
  25364.  
  25365.  
  25366.  556. How to Do a Print Screen within a Program
  25367.  
  25368.  Product Version(s): 5.10
  25369.  Operating System:   MS-DOS
  25370.  Flags: ENDUSER |
  25371.  Last Modified:  7-MAR-1990    ArticleIdent: Q59380
  25372.  
  25373.  The code below demonstrates how to do a print screen from within a
  25374.  program under MS-DOS. This is done by executing INT 5 within a
  25375.  program.
  25376.  
  25377.  The interrupt service directs all its output to the default printer.
  25378.  The print-screen service prints text or graphics. In graphics mode,
  25379.  GRAPHICS.COM must be loaded before invoking the print-screen service.
  25380.  
  25381.  INT 5 does not return any values but the status code is available at
  25382.  memory location 0050:0000. The values are as follows:
  25383.  
  25384.     00   no error occurred
  25385.     01   indicates that a print-screen operation is in progress
  25386.     FF   the previous print screen was not successful.
  25387.  
  25388.  Code Example
  25389.  ------------
  25390.  
  25391.    #include <stdio.h>
  25392.    #include <dos.h>
  25393.  
  25394.    void main (void)
  25395.    {
  25396.       int  *result;
  25397.       struct REGS inregs, outregs;
  25398.  
  25399.    /* inregs and outregs are never used but necessary
  25400.       for the int86 function.
  25401.    */
  25402.  
  25403.       puts("This is a test of prtscr() function.");
  25404.       int86(0x5, &inregs, &outregs);
  25405.  
  25406.       *result = (int *) 0x00500000;
  25407.       switch( *result )
  25408.       {
  25409.          case 0:
  25410.            puts("No error occurred.");
  25411.            break;
  25412.          case 1;
  25413.            puts("Print Screen in progress....");
  25414.            break;
  25415.          case 0xFF;
  25416.            puts("ERROR occurred during print screen");
  25417.            break;
  25418.       }
  25419.    }
  25420.  
  25421.  
  25422.  557. Cannot Open Compiler Intermediate File
  25423.  
  25424.  Product Version(s): 5.10   | 5.10
  25425.  Operating System:   MS-DOS | OS/2
  25426.  Flags: ENDUSER |
  25427.  Last Modified: 17-DEC-1990    ArticleIdent: Q59479
  25428.  
  25429.  In DOS mode, the error number for the "cannot open compiler
  25430.  intermediate file" message is C1042; in OS/2, the error number is
  25431.  C1043. This is caused by an incorrect setting of the TMP environment
  25432.  variable, when a semicolon ends the path. For example:
  25433.  
  25434.     TMP=C:\TMP;
  25435.  
  25436.  This causes the compiler to return the following error message:
  25437.  
  25438.     fatal error C1042: cannot open compiler intermediate file -- DOS
  25439.  
  25440.  or
  25441.  
  25442.     fatal error C1043: cannot open compiler intermediate file -- OS/2
  25443.  
  25444.  The correct way to set up the TMP environment variable is as follows:
  25445.  
  25446.     >SET TMP=C:\TMP<RETURN>
  25447.  
  25448.  It is important that the environment string does not end with a
  25449.  semicolon because the compiler appends the intermediate filename to
  25450.  the TMP path. By removing the semicolon from the path, the compiler
  25451.  can create the file correctly.
  25452.  
  25453.  Since there are other Microsoft products that utilize the TMP
  25454.  environment variable, it is safe to remove the semicolon from the end
  25455.  of the TMP environment variable path.
  25456.  
  25457.  This is true only for the TMP variable because other environment
  25458.  variables are used only for a search path.
  25459.  
  25460.  
  25461.  558. L2022, L2029 on PM Functions Not Prototyped As EXPENTRY
  25462.  
  25463.  Product Version(s): 5.10
  25464.  Operating System:   OS/2
  25465.  Flags: ENDUSER | o_os2sdk
  25466.  Last Modified: 15-MAR-1990    ArticleIdent: Q59489
  25467.  
  25468.  Problem:
  25469.  
  25470.  I receive the following error messages when I link my PM (Presentation
  25471.  Manager) program:
  25472.  
  25473.     LINK : error L2022: ClientWndProc (alias ClientWndProc) :
  25474.            export undefined
  25475.  
  25476.     LINK : error L2029 : 'ClientWndProc' : unresolved external
  25477.  
  25478.  Response:
  25479.  
  25480.  Most frequently, this problem is caused by having an /NOI linker
  25481.  option, which forces the linker to distinguish between uppercase and
  25482.  lowercase. For more information, search the knowledge base using the
  25483.  following query:
  25484.  
  25485.     L2022 and L2029 and /noi
  25486.  
  25487.  These linker error messages may also occur if you forget to prototype
  25488.  your functions with the EXPENTRY keyword. The EXPENTRY keyword is
  25489.  defined in OS2DEF.H as follows:
  25490.  
  25491.     #define EXPENTRY far pascal
  25492.  
  25493.  The "pascal" keyword instructs the compiler to use left-to-right
  25494.  calling sequences for the function it modifies. The keyword also
  25495.  causes the conversion of the function's name to uppercase letters.
  25496.  
  25497.  Not using the EXPENTRY keyword means that your function names are not
  25498.  converted to uppercase, so even though you declare a .DEF file, which
  25499.  includes the following line
  25500.  
  25501.     EXPORTS        ClientWndProc
  25502.  
  25503.  the linker cannot resolve definitions for the function because it does
  25504.  not see ClientWndProc and CLIENTWNDPROC as being equal.
  25505.  
  25506.  
  25507.  559. A2071 and A2006 with Assembly Code from a C Program
  25508.  
  25509.  Product Version(s): 5.10   | 5.10
  25510.  Operating System:   MS-DOS | OS/2
  25511.  Flags: ENDUSER | h_masm s_quickc s_quickasm fixlist6.00
  25512.  Last Modified: 15-APR-1990    ArticleIdent: Q59608
  25513.  
  25514.  When using the /Fa switch (generate assembly language listing) and the
  25515.  /AL switch (large memory model) with C 5.10, the compiler will
  25516.  generate some slightly incorrect assembly code in the .ASM file. When
  25517.  this assembly code is run through MASM, MASM will give the following
  25518.  errors:
  25519.  
  25520.     A2071:  Forward needs override or FAR
  25521.     A2006:  Phase error between passes
  25522.  
  25523.  Specifically, these errors occur in a module that has a function
  25524.  calling another function within the same module. In this case, it is
  25525.  possible to make a NEAR call to the specified function. Because the
  25526.  function being called is a FAR function (in large memory model), CS
  25527.  must be pushed onto the stack to correct problems that arise.
  25528.  
  25529.  The assembly code produced by C 5.10 does not specify that the call to
  25530.  the function is NEAR, although it still pushes CS onto the stack prior
  25531.  to calling the function. Because the current memory model is large,
  25532.  and the type of call is not specified, a FAR call is assumed.
  25533.  
  25534.  When the function returns (with a RET), both CS and IP are popped off
  25535.  of the stack, which the call automatically put onto the stack. You are
  25536.  left with an extra CS still on the stack.
  25537.  
  25538.  To work around this problem, it is important to force a NEAR call to
  25539.  the function.
  25540.  
  25541.  The following is an example of the C code used to produce the
  25542.  assembly code:
  25543.  
  25544.  #include <stdio.h>
  25545.  
  25546.  void main (void);
  25547.  int  r1   (void);
  25548.  
  25549.  void main (void)
  25550.  {
  25551.     printf ("Foo\n");
  25552.     r1 ();
  25553.     printf ("Bar\n");
  25554.  }
  25555.  
  25556.  int r1 (void)
  25557.  {
  25558.     return (1);
  25559.  }
  25560.  
  25561.  The following is a piece of the assembly code, the important piece in
  25562.  this case:
  25563.          .
  25564.          .
  25565.          .
  25566.     push  cs
  25567.     call  _r1
  25568.     mov   WORD PTR [bp-2], ax  ; rc
  25569.          .
  25570.          .
  25571.          .
  25572.  Because these procedures are both declared as FAR, it is assumed that
  25573.  this is a FAR call. Since that is the case, it is not necessary to
  25574.  push CS.
  25575.  
  25576.  To correct the problem, you can change the call to the following:
  25577.          .
  25578.          .
  25579.          .
  25580.     push  cs
  25581.     call  NEAR PTR _r1
  25582.     mov   WORD PTR [bp-2], ax  ; rc
  25583.          .
  25584.          .
  25585.          .
  25586.  In this case, you are forcing the assembler to notice that only the
  25587.  offset is necessary on the stack. When the RET is encountered, both
  25588.  words (offset and segment) will be popped off of the stack.
  25589.  
  25590.  It is necessary to make these changes for each call to a function that
  25591.  can be made with a near call. Calls that are made to functions in
  25592.  another module are FAR by default because they are external, so they
  25593.  aren't a problem.
  25594.  
  25595.  If the .ASM code is assembled with Quick Assembler, the same errors
  25596.  will result if the two-pass option is turned on. With only one pass,
  25597.  the phase error is not generated. Either way, the same correction
  25598.  applies in both cases.
  25599.  
  25600.  
  25601.  560. How to Find the Load Size Required for a Program
  25602.  
  25603.  Product Version(s): 4.00 5.00 5.10
  25604.  Operating System:   MS-DOS
  25605.  Flags: ENDUSER | s_quickc s_quickasm
  25606.  Last Modified:  9-APR-1990    ArticleIdent: Q59768
  25607.  
  25608.  The final allocated segment within a program is stored in the second
  25609.  word of its Program Segment Prefix (PSP). To find the size of the
  25610.  program in paragraphs, subtract the actual segment of the PSP from
  25611.  this segment number. This is useful in a number of applications
  25612.  including finding the amount of memory neccessary to store a TSR
  25613.  (terminate and stay) program.
  25614.  
  25615.  In Microsoft C, the segment of the PSP is stored in the global
  25616.  variable _psp. This makes program load size easily accessible within C
  25617.  programs as demonstrated below. For more information on the PSP, see
  25618.  the "MS-DOS Encyclopedia," Pages 108-111.
  25619.  
  25620.  Sample Code
  25621.  -----------
  25622.  
  25623.  #include<dos.h>
  25624.  
  25625.  extern unsigned _psp;       /* segment of PSP                */
  25626.  unsigned size;              /* size of program in paragraphs */
  25627.  unsigned far *psp_pointer;  /* pointer to beginning of PSP   */
  25628.  
  25629.           /* psp_pointer[1] will contain the final allocated  */
  25630.           /* segment of the program stored in the second word */
  25631.           /* of the Program Segment Prefix.                   */
  25632.  
  25633.  void main(void)
  25634.  {
  25635.       FPSEG(psp_pointer)=_psp;
  25636.       FPOFF(psp_pointer)=0;
  25637.  
  25638.       size=_psp_pointer[1]-_psp;
  25639.  }
  25640.  
  25641.  
  25642.  561. Determining If Your TSR Has Already Been Installed
  25643.  
  25644.  Product Version(s): 4.00 5.00 5.10
  25645.  Operating System:   MS-DOS
  25646.  Flags: ENDUSER | s_quickc s_quickasm appnote
  25647.  Last Modified: 23-MAR-1990    ArticleIdent: Q59884
  25648.  
  25649.  When writing a TSR (terminate-and-stay-resident), it is possible to
  25650.  utilize the multiplex interrupt (2fh) to determine whether your TSR
  25651.  has already been loaded into memory. Set up an Interrupt Service
  25652.  Routine (ISR) for this interrupt, which will compare the AH register
  25653.  with a predefined TSR number (ID#) and change the AL register to a
  25654.  nonzero value if the two are equal.
  25655.  
  25656.  When using the interrupt keyword in Microsoft C, registers are pushed
  25657.  onto the stack before each function call. To access these register
  25658.  values from within an ISR, just define the ISR function as accepting
  25659.  these registers as parameters.
  25660.  
  25661.  Once this is set up, the installation part of the TSR can make a call
  25662.  to the multiplex interrupt with the AH register set to the ID# of the
  25663.  TSR, and the AL register set to 00h. If the handler is currently
  25664.  installed, it will pick up these values in the AX register and then
  25665.  change the AL register to 01h and return this "installed" signal to
  25666.  the calling program. If the ID# in the AL register is not that of the
  25667.  TSR, the TSR can simply chain the interrupt back to its original
  25668.  vector.
  25669.  
  25670.  In summary, to have your TSR check to see if it is already installed,
  25671.  do the following:
  25672.  
  25673.  1. Make an int86 call with the following:
  25674.  
  25675.        inregs.h.ah=id#(0xc0-0xff)
  25676.        inregs.h.al=0x00
  25677.  
  25678.  2. If outregs.h.al != 0x00, program is in memory, don't re-install.
  25679.  
  25680.  3. Else, revector INT2fh to your own ISR. This ISR should do the
  25681.     following:
  25682.  
  25683.     a. Take as parameters the registers pushed on the stack by the
  25684.        interrupt keyword (see REGPAK below).
  25685.  
  25686.     b. Check the AH register, hibyte of the AX register, with a TSR
  25687.        ID#(0xc0-0xff).
  25688.  
  25689.     c. If AH=TSR ID#, change al to 0x01.
  25690.  
  25691.     d. Else, chain to the old INT2fh vector.
  25692.  
  25693.  4. Terminate and stay resident.
  25694.  
  25695.  The following is a simple example of an ISR that would accomplish Step
  25696.  3 (above) nicely with a TSR ID# of 0xc9. For more information about
  25697.  the multiplex interrupt and its function, please refer to "The New
  25698.  Peter Norton Programmer's Guide to The IBM PC & PS/2," Page 303-306.
  25699.  For an example of a TSR, see the application note "TSR Example
  25700.  Dirzap.C," which is available from Microsoft Product Support Services
  25701.  by calling (206) 454-2030.
  25702.  
  25703.  Sample Program
  25704.  --------------
  25705.  
  25706.  void (interrupt far *original_int2fh)(); /*set to original*/
  25707.                                           /* int2fh handler*/
  25708.  
  25709.  #define HIBYTE(x) (((unsigned) (x) >> 8) & 0xff)
  25710.  
  25711.  #define REGPAK unsigned es, unsigned ds, unsigned di, \
  25712.                 unsigned si, unsigned bp, unsigned sp, \
  25713.                 unsigned bx, unsigned dx, unsigned cx, \
  25714.                 unsigned ax, unsigned ip, unsigned cs, \
  25715.                 unsigned flags
  25716.  
  25717.  void interrupt far new_int2fh(REGPAK)
  25718.  {
  25719.       if (HIBYTE(ax)==0xc9) /* check TSR ID# */
  25720.            ax=0xc901;       /* set AL to 01  */
  25721.       else
  25722.            _chain_intr(original_int2fh);
  25723.  }
  25724.  
  25725.  
  25726.  562. Read() Run-Time Function Example Is Incorrect
  25727.  
  25728.  Product Version(s): 5.00 5.10 | 5.10
  25729.  Operating System:   MS-DOS    | OS/2
  25730.  Flags: ENDUSER | docerr
  25731.  Last Modified: 17-JUL-1990    ArticleIdent: Q59885
  25732.  
  25733.  On Page 481 of the "Microsoft C Optimizing Compiler: Run-Time Library
  25734.  Reference," Version 5.1 manual, the sample program for read() is
  25735.  incorrect. The conditional statement for the function read() should
  25736.  check for the value 65535 (0xFFFF or -1 for a signed int), instead of
  25737.  less than or equal to 0 (zero). Since bytesread is declared as an
  25738.  unsigned int, the value 0xFFFF is stored as 65535.
  25739.  
  25740.  Sample Code
  25741.  -----------
  25742.  
  25743.  #include <fcntl.h>            /* Needed only for O_RDWR definition */
  25744.  #include <io.h>
  25745.  #include <stdio.h>
  25746.  
  25747.  char buffer[60000];
  25748.  
  25749.  void main (void)
  25750.  {
  25751.    int fh;
  25752.    unsigned int nbytes = 60000, bytesread;
  25753.  
  25754.    /* Open file for input: */
  25755.    if ((fh = open ("data", O_RDONLY)) == -1)
  25756.    {
  25757.          perror ("open failed on input file");
  25758.          exit(1);
  25759.    }
  25760.  
  25761.    /* Read in input: */
  25762.  
  25763.    bytesread = read (fh, buffer, nbytes);
  25764.    if ((bytesread == 0) || (bytesread == 65535))
  25765.      perror ("Problem reading file");
  25766.    else
  25767.      printf ("Read %u bytes from file\n", bytesread);
  25768.  }
  25769.  
  25770.  
  25771.  563. How to Write Directly to Video Memory Under OS/2
  25772.  
  25773.  Product Version(s): 5.10
  25774.  Operating System:   OS/2
  25775.  Flags: ENDUSER |
  25776.  Last Modified: 23-MAR-1990    ArticleIdent: Q59837
  25777.  
  25778.  Question:
  25779.  
  25780.  I am porting an application from DOS to OS/2 that writes directly to
  25781.  screen memory. If I run it from OS/2, it gives me a protection
  25782.  violation whenever I attempt to write directly to screen memory. How
  25783.  is this done under OS/2?
  25784.  
  25785.  Response:
  25786.  
  25787.  Under OS/2, you can use the VioGetPhysBuf API call to obtain a 16-bit
  25788.  segment selector to the physical screen buffer. You can then use the
  25789.  MAKEP macro to obtain a 32-bit far pointer to screen memory.
  25790.  
  25791.  It is important to note that your program MUST be the current
  25792.  foreground session when writing to the screen buffer obtained by
  25793.  VioGetPhysBuf. If you switch the program to the background, OS/2
  25794.  temporarily invalidates the selectors to protect the integrity of the
  25795.  display. Any attempt to write to these selectors when the process is
  25796.  not in the foreground results in a general protection violation. You
  25797.  can use the VioScrLock API to ensure that your process will not be
  25798.  swapped to the background while writing to the video buffer.
  25799.  
  25800.  The following program demonstrates how to write directly to the
  25801.  monochrome screen buffer under OS/2.
  25802.  
  25803.  Sample Code
  25804.  -----------
  25805.  
  25806.  /*
  25807.   * MONO.C
  25808.   *
  25809.   * Writes directly to the monochrome screen buffer.
  25810.   *
  25811.   * Uses VioScrLock and VioScrUnlock to ensure that the program doesn't
  25812.   * get swapped to the background while writing to the video buffer.
  25813.   *
  25814.   * This program basically clears the monochrome screen buffer.
  25815.   *
  25816.   */
  25817.  
  25818.  #define INCL_VIO
  25819.  #define INCL_DOSPROCESS
  25820.  
  25821.  #define MONOBUF     (char far *) 0xB0000L  /* Address of mono screen
  25822.                                             /* buffer */
  25823.  #define BYTE_SIZE   4000                   /* 80x25 * 2 */
  25824.  
  25825.  #include <os2.h>
  25826.  #include <stdio.h>
  25827.  #include <conio.h>
  25828.  
  25829.  void main (void)
  25830.  {
  25831.      VIOPHYSBUF viopbBuf;
  25832.      PCH pchScreen;
  25833.      USHORT usStatus;
  25834.      int i;
  25835.  
  25836.      viopbBuf.pBuf = MONOBUF;
  25837.      viopbBuf.cb = BYTE_SIZE;
  25838.  
  25839.      /* Lock the video buffer so bad things don't happen. */
  25840.      VioScrLock(LOCKIO_NOWAIT, (PBYTE) &usStatus, 0);
  25841.  
  25842.      if (usStatus != LOCK_SUCCESS) {
  25843.          printf ("ERROR: Somebody else has the video buffer.\n");
  25844.          DosExit (EXIT_PROCESS, usStatus);
  25845.      }
  25846.  
  25847.      /* Grab the video buffer. */
  25848.      usStatus = VioGetPhysBuf(&viopbBuf, 0);
  25849.      if (usStatus) {
  25850.          printf ("VioGetPhysBuf failed returncode %d.\n",usStatus);
  25851.          DosExit (EXIT_PROCESS, usStatus);
  25852.      }
  25853.  
  25854.      /* Make a 32 bit pointer from a segment selector. */
  25855.      pchScreen = MAKEP(viopbBuf.asel[0], 0);
  25856.  
  25857.      /* Loop through memory writing spaces. Jump over attribute byte.*/
  25858.      for (i=0; i < BYTE_SIZE; i+=2)
  25859.          pchScreen[i] = ' ';
  25860.  
  25861.      /* We're done, so we can unlock the video buffer. */
  25862.      VioScrUnLock(0);
  25863.  }
  25864.  
  25865.  
  25866.  564. Floating-Point Differences Between the 8086 and MC68000
  25867.  
  25868.  Product Version(s): 5.10   | 5.10
  25869.  Operating System:   MS-DOS | OS/2
  25870.  Flags: ENDUSER | s_quickc s_quickasm h_masm endian
  25871.  Last Modified: 15-JAN-1991    ArticleIdent: Q60037
  25872.  
  25873.  Question:
  25874.  
  25875.  I am writing a file that will be exchanged between an MC68000 machine
  25876.  and an 8086 machine. I want to know how the byte ordering of the IEEE
  25877.  (Institute of Electrical and Electronic Engineers) floating-point
  25878.  format must be manipulated. In other words, how should the bits or
  25879.  bytes be reordered?
  25880.  
  25881.  Response:
  25882.  
  25883.  The byte ordering of floating point numbers in the architecture of the
  25884.  MC68000 is opposite that of the 8086; that is, the bytes are reversed.
  25885.  Microsoft C Version 5.10 conforms to the IEEE standard. The 8086
  25886.  stores floating-point numbers low-order byte to high-order byte (known
  25887.  as "little end in"). The MC68000 stores floating-point numbers
  25888.  high-order byte to low-order byte (known as "big end in"). Except for
  25889.  the bytes being reversed, the internal representation of the float is
  25890.  the same.
  25891.  
  25892.  For example, given the following floating-point number in the
  25893.  following 4-byte real data type
  25894.  
  25895.     5.27E-3
  25896.  
  25897.  the representation of that number in IEEE format would be
  25898.  
  25899.     3B AC AF F7
  25900.  
  25901.  which is equivalent in binary to the following:
  25902.  
  25903.     0011 1011 1010 1100 1010 1111 1111 0111
  25904.  
  25905.  However, an Intel machine stores this number with the bytes reversed,
  25906.  as follows:
  25907.  
  25908.     F7 AF AC 3B
  25909.  
  25910.  On the other hand, in MC68000 format, the bytes are not reversed.
  25911.  Internally the MC68000 would represent the above number as
  25912.  
  25913.     3B AC AF F7
  25914.  
  25915.  which is the same as the IEEE representation; therefore, no "manual"
  25916.  byte reversal needs to be effected.
  25917.  
  25918.  To summarize the internal interpretation of the above number, the
  25919.  following information is valid for both IEEE and MC68000 formats:
  25920.  
  25921.  The mantissa is bits 0-22, which in this case equals 2928631. The
  25922.  mantissa is assumed to be prefixed with an implied "1."; therefore,
  25923.  the full mantissa is 1.2928631. Bits 23-30 represent the exponent.
  25924.  This exponent must be adjusted by a factor of 127 (80 hex; the "bias"
  25925.  adjustment, which must be subtracted from the bitwise representation
  25926.  of the exponent). Bit 31 is 0, which implies that the exponent is
  25927.  positive. Therefore, the exponent as represented here is 119.
  25928.  Performing the following bias subtraction:
  25929.  
  25930.     119-127 = -8
  25931.  
  25932.  While the base in the original number 5.27E-3 is 10, the base of the
  25933.  internal representation is 2. Therefore, the above calculation yields
  25934.  the final result of
  25935.  
  25936.     1.2928631 X 2E-8
  25937.  
  25938.  which is the original number (allowing for some floating point
  25939.  inaccuracies).
  25940.  
  25941.  
  25942.  565. Error in memchr() Definition
  25943.  
  25944.  Product Version(s): 5.00 5.10 | 5.10
  25945.  Operating System:   MS-DOS    | OS/2
  25946.  Flags: ENDUSER | docerr
  25947.  Last Modified:  3-APR-1990    ArticleIdent: Q60045
  25948.  
  25949.  The following text shown on Page 418 of the "Microsoft C Optimizing
  25950.  Compiler: Run-Time Library Reference" for Version 5.1 manual,
  25951.  regarding the definition of the memchr() function, contains a
  25952.  misleading statement that could be confusing for some customers:
  25953.  
  25954.       void *memchr(buf,c,count);
  25955.       void *buf;                      Pointer to buffer
  25956.       int c;                  |-----> Character to copy
  25957.       size_t count;           |       Number characters
  25958.                               |
  25959.  
  25960.  Instead of "Character to copy," the definition of int c should read
  25961.  "Character to search for." Memchr() searches for, but does not copy, a
  25962.  character in a string.
  25963.  
  25964.  
  25965.  566. fscanf() Fails to Read Consecutive Lines
  25966.  
  25967.  Product Version(s): 5.10   | 5.10
  25968.  Operating System:   MS-DOS | OS/2
  25969.  Flags: ENDUSER | s_quickc
  25970.  Last Modified: 19-APR-1990    ArticleIdent: Q60336
  25971.  
  25972.  If you try to read lines of text using fscanf() from a file opened in
  25973.  text mode, and define [^\n] as the delimiter, you will find that your
  25974.  program will read only the first line of the text file.
  25975.  
  25976.  Sample Code
  25977.  -----------
  25978.  
  25979.  FILE *fin;
  25980.  char Line[80];
  25981.  
  25982.  while ( ( fscanf(fin,"%[^\n]",line) ) !=EOF  )
  25983.  {
  25984.     printf("Line = %s \n",line);
  25985.  }
  25986.  
  25987.  At first glance, the sample code appears to read and print lines from
  25988.  a text file until the end of the file is reached. However, this is not
  25989.  the case.
  25990.  
  25991.  The fscanf() function reads up to but not including the delimiting
  25992.  character. Therefore, the file stream is stopped at the first "\n" in
  25993.  the file. Subsequent fscanf() calls fail because the file is still at
  25994.  the first delimiting character and fscanf() will not move past it.
  25995.  
  25996.  To move the file stream beyond the delimiting character, the following
  25997.  are two workarounds:
  25998.  
  25999.  1. Place a fgetc() after the fscanf() to position the file pointer
  26000.     past the "\n".
  26001.  
  26002.  2. Change the fscanf() call to the following:
  26003.  
  26004.        fscanf(fin, "%[^\n]%*c", line)
  26005.  
  26006.     This automatically reads the next character.
  26007.  
  26008.  The corrected code is as follows:
  26009.  
  26010.  FILE *fin;
  26011.  char Line[80];
  26012.  
  26013.  while ( ( fscanf(fin,"%[^\n]",line) ) !=EOF  )
  26014.  {
  26015.     fgetc(fin);       // Reads in "\n" character and moves file
  26016.                       // stream past delimiting character
  26017.     printf("Line = %s \n",line);
  26018.  }
  26019.  
  26020.  
  26021.  567. C Compiler and Linker Send Errors to Stdout Not Stderr
  26022.  
  26023.  Product Version(s): 5.10
  26024.  Operating System:   MS-DOS
  26025.  Flags: ENDUSER | s_util s_pascal h_fortran h_masm docsup docerr
  26026.  Last Modified: 19-APR-1990    ArticleIdent: Q60750
  26027.  
  26028.  Current versions of the C compiler and linker send error messages to
  26029.  stdout instead of stderr. Use of the ERROUT utility shipped with
  26030.  Microsoft C Version 5.10 does not redirect these error messages to a
  26031.  file as is suggested in the documentation.
  26032.  
  26033.  The following example from the Microsoft C Version 5.10 "CodeView and
  26034.  Utilities Software Development Tools for the MS-DOS Operating System"
  26035.  manual, Page 329, is misleading:
  26036.  
  26037.     ERROUT /f C_ERRORS.DOC CL /AL /Zi /Od demo.c
  26038.  
  26039.  In the above example, the only thing printed in C_ERRORS.DOC is the C
  26040.  compiler copyright and version message. Neither the compiler or the
  26041.  linker errors appear there. This is not an error in the ERROUT
  26042.  utility, nor is it an error in C Version 5.10; it is just a change in
  26043.  the way error messages are output from the newer compilers.
  26044.  
  26045.  This new method of sending error output to stdout allows our products
  26046.  to function more easily with third-party editors that check only
  26047.  stdout for compiler and linker messages.
  26048.  
  26049.  Note: The ERROUT utility is designed for use only with executable
  26050.  programs and batch files. Attempting to use it on DOS commands, such
  26051.  as DIR, usually only results in the failure of the command.
  26052.  
  26053.  
  26054.  568. Bad Conditional Jump Generated in Inline Assembly
  26055.  
  26056.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  26057.  Operating System:   MS-DOS     | OS/2
  26058.  Flags: ENDUSER | buglist6.00 buglist6.00a
  26059.  Last Modified:  6-FEB-1991    ArticleIdent: Q69011
  26060.  
  26061.  Under the following conditions, C 6.00 and C 6.00a will generate bad
  26062.  code for conditional jumps in inline assembly blocks. If, prior to the
  26063.  conditional jump, an align or even directive is used that causes NOP
  26064.  instructions to be inserted into the code, the conditional jump
  26065.  address will be off by the number of NOPs inserted into the code. This
  26066.  will happen only when using the /Od switch for disabling optimizations
  26067.  on the compile. Optimizations should not have an affect similar to
  26068.  this on inline assembly.
  26069.  
  26070.  Using /Os, /Ot, or /Ox will resolve the problem. Removing any align or
  26071.  even directives will also eliminate the source of the problem.
  26072.  Finally, using the /qc option will also generate correct code;
  26073.  however, the /qc option does not generate the NOP instructions for the
  26074.  align and even directives as it should.
  26075.  
  26076.  Microsoft has confirmed this to be a problem in C version 6.00 and
  26077.  6.00a. We are researching this problem and will post new information
  26078.  here as it becomes available.
  26079.  
  26080.  Sample Code
  26081.  -----------
  26082.  
  26083.  void main (void)
  26084.  {
  26085.     _asm
  26086.     {
  26087.        even
  26088.        push  ds
  26089.        even
  26090.        jb    foo
  26091.  foo:  pop   ds
  26092.     }
  26093.  }
  26094.  
  26095.  
  26096.  569. Why locking() May Allow Only Twenty Regions to Be Locked
  26097.  
  26098.  Product Version(s): 4.x 5.x 6.00 6.00a
  26099.  Operating System:   MS-DOS
  26100.  Flags: ENDUSER | s_quickc
  26101.  Last Modified: 30-JAN-1991    ArticleIdent: Q67485
  26102.  
  26103.  The DOS SHARE.EXE command installs file sharing and locking capability
  26104.  within the DOS environment. If SHARE is executed without any
  26105.  parameters, the default number of simultaneous file locks is 20.
  26106.  Subsequently, the C locking() function will allow only twenty regions
  26107.  to be locked at the same time. To change from the default, SHARE
  26108.  should be installed with the following parameter (where n is the
  26109.  number of simultaneous regions that can be locked):
  26110.  
  26111.     SHARE /L:n
  26112.  
  26113.  
  26114.  570. C 5.00/5.10 Give "Constant Too Large" with Decimal Initializer
  26115.  
  26116.  Product Version(s): 3.00 4.00 5.00 5.10 | 5.10
  26117.  Operating System:   MS-DOS              | OS/2
  26118.  Flags: ENDUSER |
  26119.  Last Modified:  6-FEB-1991    ArticleIdent: Q11876
  26120.  
  26121.  Problem:
  26122.  
  26123.  When I attempt to use the most negative long integer, my results
  26124.  depend on whether I used decimal or hexadecimal to enter the value.
  26125.  The results also seem to vary between C version 5.00 and the newer
  26126.  compilers.
  26127.  
  26128.  For example, the following program produces the compiler warning
  26129.  "constant too big" when compiled with C 5.00:
  26130.  
  26131.  long d1, d2;
  26132.  
  26133.  void main(void)
  26134.  {
  26135.      long  d1 = -2147483648L;
  26136.      long  d2 =  0x80000000;
  26137.      printf("d1 = %ld", d1);
  26138.      printf("d2 = %ld", d2);
  26139.  }
  26140.  
  26141.  The compiler assigns the value -2147483647 to d1, although it assigns
  26142.  -2147483648 to d2. The internal representation of d1 seems incorrect.
  26143.  
  26144.  Response:
  26145.  
  26146.  In C versions 5.00 and earlier, the decimal constant -2147483648L is
  26147.  treated semantically as a unary minus sign applied to a positive
  26148.  constant, 2147483648L. The positive constant is outside the valid
  26149.  range for constants, and therefore, is reduced to the maximum positive
  26150.  long integer; thus, the message "constant too large" is issued.
  26151.  
  26152.  On the other hand, the hexadecimal constant 0x80000000 is treated
  26153.  semantically as a series of bits. It has few enough bits to fit into a
  26154.  long integer, so no message is issued. Had the constant contained too
  26155.  many bits to fit into a long integer, it too would have been reduced
  26156.  to 2^31 - 1.
  26157.  
  26158.  C version 5.10 does not complete compilation in this situation and
  26159.  halts with the error, "C2177: constant too large." This ensures that
  26160.  you will not be using an unexpected value.
  26161.  
  26162.  Beginning with C version 6.00, long constants can be initialized to
  26163.  decimal values larger than MAX_LONG (as per the ANSI draft standard),
  26164.  so this is no longer a problem at compilation time.
  26165.  
  26166.  
  26167.  571. fread() May Cause Protection Violation Under OS/2
  26168.  
  26169.  Product Version(s): 6.00 6.00a
  26170.  Operating System:   OS/2
  26171.  Flags: ENDUSER | buglist6.00 buglist 6.00a
  26172.  Last Modified: 11-FEB-1991    ArticleIdent: Q69136
  26173.  
  26174.  Under certain circumstances, fread() may issue a general protection
  26175.  violation (GP fault) under OS/2 when compiled in large model with C
  26176.  versions 6.00 and 6.00a.
  26177.  
  26178.  The sample code below allocates a 64K segment, filling it by doing 128
  26179.  fread()'s that request 512 bytes per call. In tracing through the
  26180.  code, it appears that as fread() is preparing to continue the read, it
  26181.  calculates the address of the first unused byte. Finding it to be
  26182.  beyond the end of the segment, it adds 0x20 to the segment value and
  26183.  places the result in the ES register, resulting in a general
  26184.  protection violation.
  26185.  
  26186.  Sample Code
  26187.  -----------
  26188.  
  26189.  /* Compile with -AL
  26190.   *
  26191.   */
  26192.  
  26193.  #define BUFS_PER_BLOCK   128      /* Number of word buffers per block. */
  26194.  #define WORD_BUFFER_SIZE 512
  26195.  
  26196.  #include <stdio.h>
  26197.  #include <os2.h>
  26198.  
  26199.  void main( void)
  26200.  {
  26201.     SEL  usSel;                    /* Selector for allocated memory. */
  26202.     FILE *fp;
  26203.     CHAR *ptCurrentBufferAddress;  /* Address of current word buffer. */
  26204.     INT   i;
  26205.  
  26206.     DosAllocSeg(WORD_BUFFER_SIZE * BUFS_PER_BLOCK, &usSel, SEG_GETTABLE);
  26207.     if ((fp = fopen("c:\\os2\\pmfile.exe", "r+b")) == NULL)
  26208.        printf("FOPEN FAILED\n");
  26209.     else
  26210.        printf("FOPEN SUCCEEDED\n");
  26211.     ptCurrentBufferAddress = MAKEP(usSel, 0);
  26212.     for (i = 0 ; ; i++)
  26213.        {
  26214.        fread(ptCurrentBufferAddress, WORD_BUFFER_SIZE, 1, fp);
  26215.        if (i == BUFS_PER_BLOCK - 1)
  26216.           break;
  26217.        ptCurrentBufferAddress += WORD_BUFFER_SIZE;
  26218.        }
  26219.  }
  26220.  
  26221.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  26222.  6.00a. We are researching this problem and will post new information
  26223.  here as it becomes available.
  26224.  
  26225.  
  26226.  572. Use of OFFSET and SEG on Local Variables in Inline Assembly
  26227.  
  26228.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  26229.  Operating System:   MS-DOS     | OS/2
  26230.  Flags: ENDUSER | s_quickc
  26231.  Last Modified:  6-FEB-1991    ArticleIdent: Q69012
  26232.  
  26233.  Inline assembly allows you to use the SEG and OFFSET operators to get
  26234.  the segment and offset address of variables. However, if you use the
  26235.  SEG directive on a local variable, you will get the following error
  26236.  message in C versions 6.00 and 6.00a or QuickC versions 2.50 and 2.51:
  26237.  
  26238.     error C2415: improper operand type
  26239.  
  26240.  You will not get this error with QuickC versions 2.00 and 2.01, and
  26241.  incorrect code will be generated. In all versions, using the OFFSET
  26242.  directive on a local variable will not directly give you a near
  26243.  pointer to the variable.
  26244.  
  26245.  It is important to remember that a local variable is placed on the
  26246.  stack at run time. Therefore, the compiler cannot determine its
  26247.  address at compile time. The value returned by OFFSET applied to a
  26248.  local variable actually is that variable's position on the stack
  26249.  relative to the BP register. Thus, adding the BP register to the
  26250.  OFFSET value will create a near pointer into the stack segment.
  26251.  
  26252.  Because the local variable is on the stack, the segment value of a
  26253.  local variable is simply the stack segment (SS) register. The
  26254.  following two sample programs demonstrate the incorrect and correct
  26255.  method to access a local variable address:
  26256.  
  26257.  Sample Code
  26258.  -----------
  26259.  
  26260.  // These programs show how you might try to load an address
  26261.  // of a local variable into the dx, ax register combination.
  26262.  
  26263.  // This is the wrong way to get a local variable address.
  26264.  
  26265.  void main(void)
  26266.  {
  26267.     int foo;
  26268.     _asm
  26269.     {
  26270.        mov ax, OFFSET foo
  26271.        mov dx, SEG foo
  26272.     }
  26273.  }
  26274.  
  26275.  // This is the right way to get a local variable address.
  26276.  
  26277.  void main (void)
  26278.  {
  26279.     int foo;
  26280.     _asm
  26281.     {
  26282.        mov ax, OFFSET foo
  26283.        add ax, bp
  26284.        mov dx, ss
  26285.     }
  26286.  }
  26287.  
  26288.  
  26289.  573. How Structures Are Packed with /Zp
  26290.  
  26291.  Product Version(s):
  26292.  Operating System:   6.00 6.00a | 6.00 6.00a
  26293.  Flags: MS-DOS     | OS/2
  26294.  Last Modified: 30-JAN-1991    ArticleIdent: Q67735
  26295.  ENDUSER | docerr s_quickc
  26296.  
  26297.  The C compiler contains a command-line option as well as a pragma to
  26298.  pack structures, /Zp and pack, respectively. Packing a structure means
  26299.  to align an element of a structure on a 1-, 2-, or 4-byte boundary.
  26300.  Packing can be used for indexing purposes, as well as to decrease
  26301.  processor access times. If /Zp or the pragma is not used, the default
  26302.  structure packing value is 2.
  26303.  
  26304.  The amount of padding used before a particular structure field is
  26305.  determined by the field size and packing value. The packing value may
  26306.  change the offset of particular members of the structure.
  26307.  
  26308.  All offsets of structure members are relative to 0 (zero). Each member
  26309.  size is compared to the packing value (also called the alignment
  26310.  value). The element is then aligned on a boundary of the smallest of
  26311.  the field size and packing value.
  26312.  
  26313.  Finally, the structure itself may be padded to allow for arrays of
  26314.  structures to be aligned properly. The rule is simple. All structures
  26315.  are padded to a multiple of the pack size except one case. If a
  26316.  structure is packed on 4 byte boundaries but doesn't contain any
  26317.  elements larger than 2 bytes, it is padded to a multiple of 2.
  26318.  
  26319.  Below is an example of a structure that was packed with 1-byte packing
  26320.  [/Zp1 or #pragma pack (1)]. The structure is shown first, followed by
  26321.  a summary of what happens to the structure in memory, and finally the
  26322.  generated assembly listing is shown.
  26323.  
  26324.  Structure
  26325.  ---------
  26326.  
  26327.  struct
  26328.  {
  26329.     char a;
  26330.     int b;
  26331.     char c;
  26332.  } dummy;
  26333.  
  26334.  Packed Structure (/Zp1)
  26335.  -----------------------
  26336.  
  26337.  struct
  26338.  {
  26339.     char a;
  26340.     int b;
  26341.     char c;
  26342.  }
  26343.  
  26344.  Assembly Code Generated in Small Model
  26345.  --------------------------------------
  26346.  
  26347.  _BSS SEGMENT WORD PUBLIC 'BSS'
  26348.  _BSS ENDS
  26349.  .
  26350.  .
  26351.  .
  26352.  _BSS SEGMENT
  26353.  COMM NEAR _dummy:BYTE:4
  26354.  _BSS ENDS
  26355.  
  26356.  Notice that the size in the assembly listing shows 4 bytes. Because
  26357.  the structure is exactly 4-bytes in size, there is no need for padding
  26358.  at the end.
  26359.  
  26360.  The following is an example with 2-byte packing [/Zp2 or #pragma
  26361.  pack(2)]:
  26362.  
  26363.  Structure
  26364.  ---------
  26365.  
  26366.  struct
  26367.  {
  26368.     char a;
  26369.     int b;
  26370.     char c;
  26371.  } dummy;
  26372.  
  26373.  Packed Structure (/Zp2)
  26374.  -----------------------
  26375.  
  26376.  struct
  26377.  {
  26378.     char a;
  26379.     (Filler character here)
  26380.     int b;
  26381.     char c;
  26382.     (Filler character here)
  26383.  }
  26384.  
  26385.  Assembly Code Generated in Small Model
  26386.  --------------------------------------
  26387.  
  26388.  _BSS SEGMENT WORD PUBLIC 'BSS'
  26389.  _BSS ENDS
  26390.  .
  26391.  .
  26392.  .
  26393.  _BSS SEGMENT
  26394.  COMM NEAR _dummy:BYTE:6
  26395.  _BSS ENDS
  26396.  
  26397.  In this case, notice that the int is padded to start on a 2-byte
  26398.  boundary and the actual structure was padded to be a multiple of 2.
  26399.  Therefore, the length is 6 bytes.
  26400.  
  26401.  The following is an example of a structure packed with /Zp4:
  26402.  
  26403.  Structure
  26404.  ---------
  26405.  
  26406.  struct
  26407.  {
  26408.     char a;
  26409.     int  b;
  26410.     long c;
  26411.     char d;
  26412.  } dummy;
  26413.  
  26414.  Packed Structure (/Zp4)
  26415.  -----------------------
  26416.  
  26417.  struct
  26418.  {
  26419.     char a;
  26420.     (1 padding character here)
  26421.     int  b;
  26422.     long c;
  26423.     char d;
  26424.     (3 filler characters here)
  26425.  }
  26426.  
  26427.  Assembly Code Generated in Small Model
  26428.  --------------------------------------
  26429.  
  26430.  _BSS SEGMENT WORD PUBLIC 'BSS'
  26431.  _BSS ENDS
  26432.  .
  26433.  .
  26434.  .
  26435.  _BSS SEGMENT
  26436.  COMM NEAR _dummy:BYTE:12
  26437.  _BSS ENDS
  26438.  
  26439.  This is a little more complex. The first padding occurs with the
  26440.  integer. Because the field size for an integer is 2 and the alignment
  26441.  value is 4, the integer will be aligned on a 2-byte boundary (field
  26442.  size is smaller). The long integer needs to be on a 4-byte alignment.
  26443.  However, because it is already on a 4-byte boundary, no padding
  26444.  characters are needed. Finally, because we have a long in this
  26445.  structure, the entire structure is padded to be a multiple of 4.
  26446.  
  26447.  
  26448.  574. How to Modify the Environment for a Spawned Process
  26449.  
  26450.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  26451.  Operating System:   MS-DOS                         | OS/2
  26452.  Flags: ENDUSER | s_quickc
  26453.  Last Modified: 15-JAN-1991    ArticleIdent: Q11997
  26454.  
  26455.  Question:
  26456.  
  26457.  I use the spawnl() function to allow the user to run other programs
  26458.  without exiting mine. Is there a way to change the operating system
  26459.  command prompt to remind the user to type EXIT to return to my
  26460.  program?
  26461.  
  26462.  Response:
  26463.  
  26464.  Since PROMPT is a DOS and OS/2 environment variable, you just need to
  26465.  set your own value for PROMPT in the spawned processes environment. C
  26466.  allows you to specify the environment to be handed to a child process
  26467.  in one of the following two ways:
  26468.  
  26469.  1. Use one of the spawn*e() functions. See the C run-time library
  26470.     reference or online help supplied with your compiler for specific
  26471.     details about the spawn() family of functions.
  26472.  
  26473.  2. Use the putenv() function to modify the program's own local copy of
  26474.     the environment, then use one of the spawn() functions other than
  26475.     spawn*e(). Details on the putenv() function may also be found in the
  26476.     C run-time library reference or online help.
  26477.  
  26478.  In general, a process may only alter the environment to be handed to a
  26479.  child process. The C run-time library functions give the illusion of
  26480.  being able to alter the environment space but this is accomplished by
  26481.  making a copy of the environment strings during start up and,
  26482.  thereafter, only altering this copy.
  26483.  
  26484.  
  26485.  575. How to Change Attributes of Subdirectories in a C Program
  26486.  
  26487.  Product Version(s): 3.x 4.x 5.x 6.00 6.00a | 5.10 6.00 6.00a
  26488.  Operating System:   MS-DOS                 | OS/2
  26489.  Flags: ENDUSER |
  26490.  Last Modified: 25-FEB-1991    ArticleIdent: Q69216
  26491.  
  26492.  The C run-time functions _dos_setfileattr() and _dos_getfileattr(), or
  26493.  the OS/2 API calls DosSetFileMode() and DosQFileMode(), respectively,
  26494.  allow you to set and check the attributes of files. When using the
  26495.  same functions on subdirectories, the operating system does not allow
  26496.  attributes to be set, and no error codes are returned. However,
  26497.  because a subdirectory is a special instance of a file, the system can
  26498.  be fooled into thinking that a subdirectory is a file, which will
  26499.  allow you to set the attributes of a subdirectory.
  26500.  
  26501.  Below is a listing of available attribute settings:
  26502.  
  26503.     C Run-Time   OS/2            Description                  Value
  26504.     ----------   ----            -----------                  -----
  26505.  
  26506.     _A_NORMAL    FILE_NORMAL     A file with no attributes    0x00
  26507.     _A_RDONLY    FILE_READONLY   A read-only file             0x01
  26508.     _A_HIDDEN    FILE_HIDDEN     A hidden file                0x02
  26509.     _A_SYSTEM    FILE_SYSTEM     A system file                0x04
  26510.     _A_VOLID     *               Volume label (special case)  0x08
  26511.     _A_SUBDIR    FILE_DIRECTORY  Subdirectory (special case)  0x10
  26512.     _A_ARCH      FILE_ARCHIVED   An archived file             0x20
  26513.  
  26514.   * A drive's volume label is another special-case file; there is only
  26515.     one per (logical) drive, and it is only in the root directory.
  26516.     Under OS/2, volume labels can be changed with DosSetFSInfo. Under
  26517.     DOS, there are no C run-time functions to change drive volumes. For
  26518.     more information, query on the following words:
  26519.  
  26520.        volume and attribute and 5.10
  26521.  
  26522.  From the list above, the only attributes that can be dynamically set
  26523.  are FILE_READONLY, FILE_HIDDEN, and FILE_SYSTEM (all files,
  26524.  subdirectories, and volumes entail FILE_NORMAL), and this process
  26525.  cannot be done on a directory entry that is flagged as a subdirectory
  26526.  or volume label. To change the attributes of a subdirectory, the
  26527.  attribute flag _A_SUBDIR (or FILE_DIRECTORY) should not be included.
  26528.  The code below demonstrates how to do this using either C run-time
  26529.  calls (DOS only) or OS/2 API functions (DOS and OS/2 if bound).
  26530.  
  26531.  Sample Code
  26532.  -----------
  26533.  
  26534.  #define INCL_DOSFILEMGR
  26535.  #include <os2.h>
  26536.  
  26537.  #include <dos.h>
  26538.  #include <stdlib.h>
  26539.  
  26540.  unsigned attr, newattr;
  26541.  
  26542.  void main(void)
  26543.  {
  26544.     if (DOS_MODE == _osmode)
  26545.        {
  26546.        // First get the current attribute of subdirectory '\foo'
  26547.        // If successful, 'attr' will contain at least the
  26548.        // _A_SUBDIR bit mask
  26549.  
  26550.        _dos_getfileattr( "\\foo", &attr );
  26551.  
  26552.        // Mask in new attributes and remove _A_SUBDIR from the old
  26553.        // attribute
  26554.  
  26555.        newattr = (attr | _A_HIDDEN | _A_SYSTEM | _A_RDONLY)
  26556.                    & ~_A_SUBDIR;
  26557.  
  26558.        // Set new attribute for 'foo'
  26559.  
  26560.        _dos_setfileattr( "\\foo", newattr );
  26561.        }
  26562.     else     // Here is the same using OS/2 APIs
  26563.        {
  26564.        DosQFileMode( "\\foo", &attr, 0L );
  26565.  
  26566.        newattr = (attr | FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY)
  26567.                    & ~FILE_DIRECTORY;
  26568.  
  26569.        DosSetFileMode( "\\foo", newattr, 0L );
  26570.        }
  26571.  }
  26572.  
  26573.  
  26574.  576. Getting to the Mouse from a Real-Mode C Program
  26575.  
  26576.  Product Version(s): 3.00 4.00 5.00 6.00 6.00a
  26577.  Operating System:   MS-DOS
  26578.  Flags: ENDUSER |
  26579.  Last Modified:  6-FEB-1991    ArticleIdent: Q12012
  26580.  
  26581.  Question:
  26582.  
  26583.  I am trying to access the mouse from a C program. Do you have an
  26584.  example to help get me started?
  26585.  
  26586.  Response:
  26587.  
  26588.  Below is a program example to test mouse usage from a C program. The
  26589.  mouse driver must be installed first. This type of information is
  26590.  described in the "Mouse Programming Interface" chapter of the
  26591.  "Microsoft Mouse Programmer's Reference" available from Microsoft
  26592.  Press.
  26593.  
  26594.  Sample Code
  26595.  -----------
  26596.  
  26597.  #include <stdio.h>
  26598.  #include <dos.h>
  26599.  
  26600.  int m1=0,m2=0,m3=0,m4=0;
  26601.  union REGS Mouse_regs;
  26602.  
  26603.  void mouse(void)
  26604.  {
  26605.      Mouse_regs.x.ax=m1;
  26606.      Mouse_regs.x.bx=m2;
  26607.      Mouse_regs.x.cx=m3;
  26608.      Mouse_regs.x.dx=m4;
  26609.      int86(0x33,&Mouse_regs,&Mouse_regs);
  26610.      m1=Mouse_regs.x.ax;
  26611.      m2=Mouse_regs.x.bx;
  26612.      m3=Mouse_regs.x.cx;
  26613.      m4=Mouse_regs.x.dx;
  26614.  }
  26615.  
  26616.  void main(void)
  26617.  {
  26618.      /* Turn on the mouse */
  26619.      m1 = 1;           /* SHOW MOUSE Opcode -- See reference */
  26620.      m2 = m3 = m4 = 0; /* Additional parameters (init=0) */
  26621.      mouse();          /* Make it happen */
  26622.  
  26623.      for (;;)          /* loop until both buttons are down */
  26624.         {
  26625.          m1=3;         /* Get mouse status */
  26626.          m2=m3=m4=0;
  26627.          mouse();
  26628.  
  26629.          if (m2 & 1)
  26630.             printf("Left button down\n");
  26631.          if (m2 & 2)
  26632.             printf("Right button down\n");
  26633.          if (m2 & 1 && m2 & 2)
  26634.             {
  26635.              printf("BOTH!\n");
  26636.              exit(0);
  26637.             }
  26638.         }
  26639.  }
  26640.  
  26641.  
  26642.  577. Retrieving a Disk's Volume Serial Number from C
  26643.  
  26644.  Product Version(s): 5.10 6.00 6.00a
  26645.  Operating System:   MS-DOS
  26646.  Flags: ENDUSER | s_quickc
  26647.  Last Modified: 25-FEB-1991    ArticleIdent: Q69223
  26648.  
  26649.  Beginning with MS-DOS 4.00, a semi-random 32-bit binary identification
  26650.  number (ID) is assigned to each disk that DOS formats. The volume
  26651.  serial number (or ID) is stored at offset 27H to 2AH in the boot
  26652.  sector of each disk. The following program illustrates how to retrieve
  26653.  this information:
  26654.  
  26655.  /***************************************************************/
  26656.  /*                                                             */
  26657.  /* This program reads the volume serial number (or ID) from    */
  26658.  /* the boot sector of a specified disk. The DOS interrupt 25   */
  26659.  /* Absolute Disk Read is used to read in the boot sector.      */
  26660.  /*                                                             */
  26661.  /* Note: The volume ID is only implemented from MS-DOS 4.00    */
  26662.  /*       and later.                                            */
  26663.  /*                                                             */
  26664.  /* The output consists of the OEM name and version of the      */
  26665.  /* disk-formatting program (stored at offset 03H to 0AH in the */
  26666.  /* boot sector), the disk volume label, and the disk-volume    */
  26667.  /* serial number.                                              */
  26668.  /*                                                             */
  26669.  /***************************************************************/
  26670.  
  26671.  #include <stdio.h>
  26672.  #include <stdlib.h>
  26673.  #include <string.h>
  26674.  #include <dos.h>
  26675.  #include <conio.h>
  26676.  
  26677.  char bootsector[1024];
  26678.  char volume[12];
  26679.  char ver[9];
  26680.  char block[10];
  26681.  
  26682.  void main(void)
  26683.  {
  26684.     int ax, _far *p, drive;
  26685.     struct find_t fileinfo;
  26686.     char filename[13], _far *foo, _far *q;
  26687.     union REGS inregs, outregs;
  26688.     struct SREGS segregs;
  26689.  
  26690.     printf("Enter drive number (0=A,1=B,2=C, ...): ");
  26691.     drive=getche() - '0';
  26692.  
  26693.     /**************************************/
  26694.     /* Parameter block for int 25H        */
  26695.     /* Bytes    Description               */
  26696.     /* -------  -----------               */
  26697.     /* 00H-03H  32-bit sector number      */
  26698.     /* 04H-05H  Number of sectors to read */
  26699.     /* 06H-07H  Offset of buffer          */
  26700.     /* 08H-09H  Segment of buffer         */
  26701.     /**************************************/
  26702.  
  26703.     block[0]=block[1]=block[2]=block[3]=0;
  26704.     block[4]=1;
  26705.     block[5]=0;
  26706.  
  26707.     foo=bootsector;
  26708.  
  26709.     p=(int *)&block[6];
  26710.     *p=FP_OFF(foo);
  26711.  
  26712.     p=(int *)&block[8];
  26713.     *p=FP_SEG(foo);
  26714.  
  26715.     q=block;
  26716.     inregs.h.al=(char) drive;
  26717.     inregs.x.cx=-1;
  26718.     inregs.x.bx=FP_OFF(q);
  26719.     segregs.ds=FP_SEG(q);
  26720.     ax=int86x(0x25, &inregs, &outregs, &segregs);
  26721.  
  26722.     /*** Error routine ***/
  26723.  
  26724.     if(outregs.x.cflag)
  26725.     {
  26726.        printf("\n\nerror on int 25\n");
  26727.        printf("this is AX:%04X",ax);
  26728.        exit(-1);
  26729.     }
  26730.  
  26731.     /*** Output ***/
  26732.  
  26733.     printf("\n\nDrive %c\n-------\n\n", drive +'A');
  26734.  
  26735.     strncpy(ver, &bootsector[3], 8);
  26736.     printf("OEM name and version: %s\n", ver);
  26737.  
  26738.     /* Use _dos_findfirst for the volume label */
  26739.  
  26740.     filename[0]=(char) (drive + 'A');
  26741.     filename[1]='\0';
  26742.     strcat(filename, ":\\*.*");
  26743.     if(!_dos_findfirst(filename, _A_VOLID, &fileinfo))
  26744.     printf("Volume name         : %s\n",fileinfo.name);
  26745.  
  26746.     /* Before printing serial number, check if version >= 4.x */
  26747.  
  26748.     if((ver[6]=='.')&&(ver[5]>='4')&&(ver[5]<='9'))
  26749.        printf("Serial number       : %02X%02X-%02X%02X\n\n",
  26750.                                (unsigned char) bootsector[0x2a],
  26751.                                (unsigned char) bootsector[0x29],
  26752.                                (unsigned char) bootsector[0x28],
  26753.                                (unsigned char) bootsector[0x27]);
  26754.  }
  26755.  
  26756.  
  26757.  578. Comments in .COD Listing Are Wrong When Using _fastcall
  26758.  
  26759.  Product Version(s): 6.00a  | 6.00a
  26760.  Operating System:   MS-DOS | OS/2
  26761.  Flags: ENDUSER | buglist6.00a fastcall
  26762.  Last Modified: 30-JAN-1991    ArticleIdent: Q67513
  26763.  
  26764.  When using the code below with the _fastcall keyword, and compiling
  26765.  with the /Fc option for a code listing, the listing generates correct
  26766.  code but incorrectly comments the values that are being pushed.
  26767.  
  26768.  Using the /Gs (recommended for using _fastcall) and /Fc compile-line
  26769.  options will generate a code listing that produces wrong comments for
  26770.  the following statements:
  26771.  
  26772.     mov ch, byte ptr top
  26773.     mov cl, byte ptr left
  26774.     mov dh, byte ptr bot
  26775.  
  26776.  The code listing below shows the incorrect comments that are
  26777.  generated:
  26778.  
  26779.  ;|***                   mov al, byte ptr lines
  26780.  ; Line 13
  26781.          *** 000018   8a 46 06   mov     al,BYTE PTR [bp+6] ;lines
  26782.  ;|***                   mov bh, byte ptr attr
  26783.  ; Line 14
  26784.          *** 00001b   8a 7e fe   mov     bh,BYTE PTR [bp-2] ;attr
  26785.  ;|***                   mov ch, byte ptr top
  26786.  ; Line 15
  26787.          *** 00001e   8a 6e fe   mov     ch,BYTE PTR [bp-8]
  26788.  ;|***                   mov cl, byte ptr left
  26789.  ; Line 16
  26790.          *** 000021   8a 4e fa   mov     cl,BYTE PTR [bp-6] ;top
  26791.  ;|***                   mov dh, byte ptr bot
  26792.  ; Line 17
  26793.          *** 000024   8a 76 fc   mov     dh,BYTE PTR [bp-4] ;left
  26794.  ;|***                   mov dl, byte ptr right
  26795.  ; Line 18
  26796.          *** 000027   8a 56 08   mov     dl,BYTE PTR [bp+8] ;right
  26797.  
  26798.  Notice that the comments after the ch, cl, dh mov statements are not
  26799.  the same variable names that were actually moved into these registers.
  26800.  For instance, the statement
  26801.  
  26802.      mov ch, byte ptr top
  26803.  
  26804.  has no comment after it stating what variable was used. However, the
  26805.  statement
  26806.  
  26807.      mov cl, byte ptr left
  26808.  
  26809.  has a comment of ";top" stating that top was moved in. Obviously,
  26810.  "top" was moved into the ch register in the previous statement.
  26811.  
  26812.  Note: The generated code in this listing, as well as in the OBJ, is
  26813.  correct.
  26814.  
  26815.  Sample Code
  26816.  -----------
  26817.  
  26818.  static void _fastcall scr_scroll
  26819.            (int top, int left, int bot, int right, int lines, int dir)
  26820.  {
  26821.          char attr = 7;
  26822.  
  26823.          _asm
  26824.                  {
  26825.                          mov ah, byte ptr dir
  26826.                          or  ah, ah
  26827.                          mov ah, 7
  26828.                          jnz around
  26829.                          dec ah
  26830.                  around:
  26831.                          mov al, byte ptr lines
  26832.                          mov bh, byte ptr attr
  26833.                          mov ch, byte ptr top
  26834.                          mov cl, byte ptr left
  26835.                          mov dh, byte ptr bot
  26836.                          mov dl, byte ptr right
  26837.                          int 0x10
  26838.                  }
  26839.  }
  26840.  
  26841.  void main(void)
  26842.  {
  26843.          int t=0,l=0,b=0,r=0,li=0,d=0;
  26844.          scr_scroll(t,l,b,r,li,d);
  26845.  }
  26846.  
  26847.  Microsoft has confirmed this to be a problem in the C version 6.00a.
  26848.  We are researching this problem and will post new information here as
  26849.  it becomes available.
  26850.  
  26851.  
  26852.  579. Directly Accessing Video Memory from a C Program
  26853.  
  26854.  Product Version(s): 3.00 4.00 5.00 6.00 6.00a
  26855.  Operating System:   MS-DOS
  26856.  Flags: ENDUSER |
  26857.  Last Modified:  6-FEB-1991    ArticleIdent: Q12010
  26858.  
  26859.  Question:
  26860.  
  26861.  How can we access the video memory bytes located in segment B800
  26862.  offset 0? We want to move blocks of bytes directly to the graphic
  26863.  system memory in a C program.
  26864.  
  26865.  Response:
  26866.  
  26867.  When programs access special memory directly, they become less
  26868.  portable, and may not run as expected on other or future machines.
  26869.  Given this warning, the sample code below is a function that directly
  26870.  accesses video memory.
  26871.  
  26872.  Sample Code
  26873.  -----------
  26874.  
  26875.  /* Video.c -- Function to place a character and its standard
  26876.                attribute into the desired video memory page.
  26877.  
  26878.        Note: This function assumes that the display is set to
  26879.             Color or Monochrome, 80 column, text mode.
  26880.  */
  26881.  
  26882.  #include <dos.h>
  26883.  
  26884.  #define MAKELONG(a, b)  ((long)(((unsigned)a) \
  26885.                         | ((unsigned long)((unsigned)b)) << 16))
  26886.  #define COLORTEXT_BUFFER   0XB800
  26887.  
  26888.  void video(int pageno, int row, int col, char *ch, char attrib)
  26889.  /* pageno : page number to load character into (0 to 3) */
  26890.  /* row    : row of location 0 to 24                     */
  26891.  /* col    : column of location 0 to 79                  */
  26892.  /* ch     : character to be placed there                */
  26893.  /* attrib : standard character attribute                */
  26894.  {
  26895.      unsigned int offset; /* Offset from the segment address of
  26896.                              the desired video page */
  26897.      char far *y;         /* Long Pointer to the position in memory
  26898.                              where we will put the character and
  26899.                              it's attribute (next byte) */
  26900.  
  26901.  /* Calc the in-page offset w/page number offset and segment address */
  26902.      offset = (unsigned int) ((row * 160 )+(col*2)+(pageno*4096));
  26903.  
  26904.  /* Set the character. */
  26905.      y = (char far *)MAKELONG( offset, COLORTEXT_BUFFER);
  26906.      *y = *ch;
  26907.  
  26908.  /*  Set the attribute byte. See a DOS programmers reference for
  26909.      more information on video attributes. */
  26910.      offset++;
  26911.      y = (char far *)MAKELONG( offset, COLORTEXT_BUFFER);
  26912.      *y = attrib;
  26913.  }
  26914.  
  26915.  
  26916.  580. C1001: Internal Compiler Error: regMD.c, Lines 3881 and 3837
  26917.  
  26918.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  26919.  Operating System:   MS-DOS     | OS/2
  26920.  Flags: ENDUSER | buglist6.00 buglist6.00a
  26921.  Last Modified: 25-FEB-1991    ArticleIdent: Q69224
  26922.  
  26923.  The C version 6.00a compiler produces the following internal compiler
  26924.  error when the sample program below is compiled with the intrinsic
  26925.  optimization (/Oi):
  26926.  
  26927.     file.c(7) : fatal error C1001: Internal Compiler Error
  26928.                 (compiler file '@(#)regMD.c:1.110', line 3881)
  26929.                 Contact Microsoft Product Support Services
  26930.  
  26931.  With C version 6.00, the error is the same, except it is line 3837.
  26932.  
  26933.  Using the function version of strlen() eliminates the problem.
  26934.  
  26935.  Microsoft has confirmed this to be a problem in the C compiler
  26936.  versions 6.00 and 6.00a. We are researching this problem and will post
  26937.  new information here as it becomes available.
  26938.  
  26939.  Sample Code
  26940.  -----------
  26941.  
  26942.  #include <stdio.h>
  26943.  
  26944.  void main(void)
  26945.  {
  26946.     char * string;
  26947.     int j;
  26948.  
  26949.     j = 8 * strlen(string);
  26950.  }
  26951.  
  26952.  
  26953.  581. Questions and Answers About the Use of malloc() and _fmalloc()
  26954.  
  26955.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  26956.  Operating System:   MS-DOS                         | OS/2
  26957.  Flags: ENDUSER | s_quickc
  26958.  Last Modified: 15-JAN-1991    ArticleIdent: Q12159
  26959.  
  26960.  Question:
  26961.  
  26962.  I am designing a product using the medium model, but need some dynamic
  26963.  memory larger than the default segment for temporary storage and
  26964.  semi-permanent main data structures. Things seem to be working
  26965.  properly, but I have the following questions:
  26966.  
  26967.  1. Can malloc() and _fmalloc() be used together without restriction,
  26968.     for example, using malloc() for the temporary data and _fmalloc()
  26969.     for the semi-permanent data?
  26970.  
  26971.  2. Are there ever any user-visible delays for garbage collection
  26972.     (compression of string space)?
  26973.  
  26974.  3. Are there fragmentation risks? In experimenting with _fmalloc(), it
  26975.     appears that contiguous blocks freed at different times are
  26976.     automatically consolidated, which should reduce the fragmentation
  26977.     risk.
  26978.  
  26979.  4. Does _fmalloc() ensure that any single assignment is within one
  26980.     data segment (so assembly move/access routines need not deal with
  26981.     segment boundaries)?
  26982.  
  26983.  Response:
  26984.  
  26985.  1. Yes, malloc() and _fmalloc() may be used together. They both track
  26986.     their memory allocation separately and, in fact, you must use two
  26987.     different functions to free the allocated data: free() and _ffree()
  26988.     respectively.
  26989.  
  26990.  2. The malloc() functions do not perform any form of garbage
  26991.     collection. You allocate the space and you decide when it is to be
  26992.     freed up for later usage. Therefore, there will be no visible or
  26993.     unexpected time delays during execution.
  26994.  
  26995.  3. The _fmalloc() function will consolidate adjacent free blocks. This
  26996.     reduces the risk of fragmentation problems.
  26997.  
  26998.  4. The _fmalloc() function will not allocate across segment
  26999.     boundaries. Only halloc() (the huge-model memory allocation
  27000.     routine) can perform this function. Therefore you are assured that
  27001.     no one allocation will cross a segment boundary (because it cannot
  27002.     allocate larger then 64K).
  27003.  
  27004.  
  27005.  582. Use Timer Interrupt to Maintain Time Independent of CPU Speed
  27006.  
  27007.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
  27008.  Operating System:   MS-DOS
  27009.  Flags: ENDUSER | s_quickc
  27010.  Last Modified: 15-JAN-1991    ArticleIdent: Q12131
  27011.  
  27012.  Question:
  27013.  
  27014.  Is there a way to set up a function that will pause for n units of
  27015.  time without being altered on a faster or slower machine (for example,
  27016.  from a PC to an AT).
  27017.  
  27018.  Response:
  27019.  
  27020.  Set up a routine to handle the timer tick interrupt. This will be the
  27021.  same on all machines (about 18.2 times per second with interrupts
  27022.  enabled). The timer tick is interrupt 1C and can be modified for
  27023.  access by your own routine.
  27024.  
  27025.  
  27026.  583. _bheapseg: Return Value Documented Incorrectly
  27027.  
  27028.  Product Version(s): 6.00 6.00a  | 6.00 6.00a
  27029.  Operating System:   MS-DOS      | OS/2
  27030.  Flags: ENDUSER | docerr
  27031.  Last Modified: 25-FEB-1991    ArticleIdent: Q69237
  27032.  
  27033.  The return value for the _bheapseg function is documented incorrectly
  27034.  on page 147 of the "Microsoft C Reference," in the online help for C
  27035.  6.00, and in the online help for QuickC versions 2.50 and 2.51.
  27036.  
  27037.  On page 147 of the "Microsoft C Reference," the line that reads
  27038.  
  27039.     Returns     The selector for the newly allocated segment
  27040.                 if successful; -1 if not.
  27041.  
  27042.  should read as follows:
  27043.  
  27044.     Returns     The selector for the newly allocated segment
  27045.                 if successful; 0 (_NULLSEG) if not.
  27046.  
  27047.  The online help mentions the correct return value for the _bheapseg
  27048.  function in the "Summary" section, except that it specifies NULLSEG
  27049.  instead of _NULLSEG. The paragraph in the "Description" section titled
  27050.  "Return Value" incorrectly documents the return value as -1.
  27051.  
  27052.  
  27053.  584. Call ROM BIOS Routines to Check the Printer Status
  27054.  
  27055.  Product Version(s): 5.00 5.10 6.00 6.00a
  27056.  Operating System:   MS-DOS
  27057.  Flags: ENDUSER |
  27058.  Last Modified: 15-JAN-1991    ArticleIdent: Q12110
  27059.  
  27060.  Question:
  27061.  
  27062.  We are sending text to the printer using fopen("prn","w"). Many of our
  27063.  clients get the following message:
  27064.  
  27065.     Writing error on device PRN -- abort, retry, ignore.
  27066.  
  27067.  How can we check the printer status so that we can avoid this?
  27068.  
  27069.  Response:
  27070.  
  27071.  Although there is no portable method for checking printer status in C,
  27072.  you can get printer status information via the ROM BIOS. You can
  27073.  obtain status information by calling _bios_printer(), which is an
  27074.  interface to INT 17H, function 2. You can also call BIOS interrupt
  27075.  functions through the int86() functions. See the online help or the
  27076.  run-time library reference for your version of the compiler for more
  27077.  information about these functions.
  27078.  
  27079.  You may want to handle the error by revectoring the critical error
  27080.  handler interrupt (24H), which will allow you to intercept the "abort,
  27081.  retry" message before the user receives it. You then can decide
  27082.  whether to substitute your own message, such as "Printer off line: set
  27083.  printer on line and press Y to continue."
  27084.  
  27085.  More information on the ROM BIOS routines and interrupt handlers can
  27086.  be found in the following two books from Microsoft Press:
  27087.  
  27088.  1. "The Peter Norton Programmer's Guide to the IBM PC" (r)
  27089.  
  27090.  2. "Advanced MS-DOS" by Ray Duncan
  27091.  
  27092.  
  27093.  585. C1001: Internal Compiler Error: exphelp.c, Line 617
  27094.  
  27095.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27096.  Operating System:   MS-DOS     | OS/2
  27097.  Flags: ENDUSER | buglist6.00 buglist6.00a
  27098.  Last Modified: 25-FEB-1991    ArticleIdent: Q69289
  27099.  
  27100.  The Microsoft C Compiler versions 6.00 and 6.00a produce the following
  27101.  internal compiler error when the sample program below is compiled with
  27102.  default optimization and large memory model (/AL):
  27103.  
  27104.     mem2.c(4) : fatal error C1001: Internal Compiler Error
  27105.                 (compiler file '@(#)exphelp.c:1.117', line 617)
  27106.                 Contact Microsoft Product Support Services
  27107.  
  27108.  The above error occurs only when using any one of the optimizations
  27109.  /Oi, /Oa, /Oc, /On, /Op, /Or, /Os, /Ot, /Ow, /Oz, or using default
  27110.  optimizations. Furthermore, the source must be compiled in compact,
  27111.  large, or huge memory models.
  27112.  
  27113.  To work around the problem, compile without using default
  27114.  optimizations or any of the above mentioned options. You may elect to
  27115.  disable optimizations for the function that is producing the error. Do
  27116.  this by using the "optimize" pragma. Another valid workaround is to
  27117.  compile using the /qc (Quick Compile) option, which also does not
  27118.  produce the error.
  27119.  
  27120.  Sample Code
  27121.  -----------
  27122.  
  27123.  /* Compile with /AL */
  27124.  
  27125.  void func(int *memoryPtr,unsigned long pageLow)
  27126.  {
  27127.      if ((*memoryPtr)>0)
  27128.        pageLow=(unsigned long)memoryPtr>>28;
  27129.  }
  27130.  
  27131.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  27132.  6.00a. We are researching this problem and will post new information
  27133.  here as it becomes available.
  27134.  
  27135.  
  27136.  586. Bad Code Generated for Function Returning _self Based Pointer
  27137.  
  27138.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27139.  Operating System:   MS-DOS     | OS/2
  27140.  Flags: ENDUSER | buglist6.00 buglist6.00a
  27141.  Last Modified: 30-JAN-1991    ArticleIdent: Q67612
  27142.  
  27143.  The C versions 6.00 and 6.00a compilers will generate incorrect code
  27144.  for a function that returns a pointer based on self. The code
  27145.  generated for the return statement introduces an extra level of
  27146.  indirection.
  27147.  
  27148.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  27149.  6.00a. We are researching this problem and will post new information
  27150.  here as it becomes available.
  27151.  
  27152.  The following program fragment demonstrates this problem. Compile the
  27153.  code with the /Fc option to generate an assembly listing, and observe
  27154.  the code in the resulting .COD file for the return statement in the
  27155.  function test().
  27156.  
  27157.  struct foo {
  27158.              int  _based((_segment) _self) *pbs;
  27159.             } far *pfoo;
  27160.  
  27161.  int far *test(void)
  27162.  {
  27163.     return(pfoo->pbs);
  27164.  }
  27165.  
  27166.  
  27167.  587. Use the signal() Function to Trap Floating-Point Exceptions
  27168.  
  27169.  Product Version(s): 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  27170.  Operating System:   MS-DOS                    | OS/2
  27171.  Flags: ENDUSER | s_quickc
  27172.  Last Modified: 15-JAN-1991    ArticleIdent: Q12127
  27173.  
  27174.  Question:
  27175.  
  27176.  Is there a way that I can trap all possible floating point exceptions
  27177.  in a C program?
  27178.  
  27179.  Response:
  27180.  
  27181.  The C signal() function allows the capture of floating-point
  27182.  exceptions.
  27183.  
  27184.  For more information on the signal() function, see the run-time
  27185.  library reference or the online help that accompanies your compiler.
  27186.  
  27187.  
  27188.  588. Promotion of char to int May Add Two Hex Digits in printf()
  27189.  
  27190.  Product Version(s): 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  27191.  Operating System:   MS-DOS               | OS/2
  27192.  Flags: ENDUSER | s_quickc hexidecimal conversion
  27193.  Last Modified: 25-FEB-1991    ArticleIdent: Q69344
  27194.  
  27195.  When trying to display a signed char in two-digit hexadecimal format, as
  27196.  follows
  27197.  
  27198.     char hex_byte = 0x80;
  27199.     printf( "The Hex value is %X", hex_byte);
  27200.  
  27201.  four digits will be displayed if the char has a value of 0x80 to 0xFF
  27202.  because of promotion of the char to a signed int. The %x and %X
  27203.  specifiers designate an unsigned hex integer, but because leading 0's
  27204.  (zeros) are dropped, values in the range of 0 to 127 produce the
  27205.  desired two digits. See the sample code below.
  27206.  
  27207.  To preserve the two-digit display for all possible values, just
  27208.  typecast the char to an unsigned char in the printf() argument list,
  27209.  as shown below:
  27210.  
  27211.     printf( "The Hex value is %X", (unsigned char)hex_byte);
  27212.  
  27213.  Another way to achieve this, if sign is of no consequence, is to
  27214.  declare the variables as unsigned char.
  27215.  
  27216.  For ANSI compliance, the compiler promotes all char arguments to
  27217.  signed int. If the type is signed char, then the value will be
  27218.  sign-extended. Thus, the int will be negative if the left-most bit of
  27219.  the char was set, resulting in a different value for the int. When an
  27220.  unsigned char is promoted, a 0 (zero) is placed in the high byte so
  27221.  that the value is retained.
  27222.  
  27223.  This promotion may also cause problems with comparisons of signed and
  27224.  unsigned chars. This situation, unlike the printf() situation, will
  27225.  produce a C4018 (signed/unsigned mismatch) warning at warning level 3
  27226.  and above, beginning with C version 6.00.
  27227.  
  27228.  This behavior is also observed in QuickC versions 2.00 and 2.50 and
  27229.  QuickC with QuickAssembler versions 2.01 and 2.51.
  27230.  
  27231.  Sample Code
  27232.  -----------
  27233.  
  27234.  #include <stdio.h>
  27235.  
  27236.  void main( void)
  27237.  {
  27238.     char goo = 127;
  27239.     char foo = 128;
  27240.  
  27241.     printf( "goo = %X\n",   goo); /* yields "7F" */
  27242.     printf( "foo = %X\n",   foo); /* yields "FF80" */
  27243.  
  27244.     /* correct way to represent the char as two hex digits "80" */
  27245.     printf( "foo = %X\n",   (unsigned char)foo);
  27246.  }
  27247.  
  27248.  
  27249.  589. File Component Constants Increased Beginning with C 6.00
  27250.  
  27251.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27252.  Operating System:   MS-DOS     | OS/2
  27253.  Flags: ENDUSER | s_quickc
  27254.  Last Modified: 25-FEB-1991    ArticleIdent: Q69349
  27255.  
  27256.  The following manifest constants (found in STDLIB.H) were changed
  27257.  beginning with C version 6.00:
  27258.  
  27259.     _MAX_PATH       260     /* max. length of full pathname */
  27260.     _MAX_DRIVE      3       /* max. length of drive component */
  27261.     _MAX_DIR        256     /* max. length of path component */
  27262.     _MAX_FNAME      256     /* max. length of filename component */
  27263.     _MAX_EXT        256     /* max. length of extension component */
  27264.  
  27265.  Prior to C 6.00, these constants were defined as follows:
  27266.  
  27267.     _MAX_PATH       144
  27268.     _MAX_DRIVE      3
  27269.     _MAX_DIR        130
  27270.     _MAX_FNAME      9
  27271.     _MAX_EXT        5
  27272.  
  27273.  These changes may cause unexpected results if filenames longer than
  27274.  eight characters are entered for use under DOS. The sample code below
  27275.  demonstrates the differences.
  27276.  
  27277.  The changes in the constants were made to allow for longer filenames
  27278.  and extensions in future operating systems, as well as the current
  27279.  implementation of the High Performance File System (HPFS) introduced
  27280.  in OS/2 version 1.20. The potential for problems is greatest when
  27281.  buffers are used that are not as big as the new constant values. This
  27282.  generally occurs when porting code from a previous version of the
  27283.  compiler to C version 6.00 or later.
  27284.  
  27285.  There are several ways to protect against problems that may occur in
  27286.  your code because of this change:
  27287.  
  27288.  1. Always declare filename buffers with the actual constants, for
  27289.     example:
  27290.  
  27291.        char file_name[_MAX_FNAME];
  27292.  
  27293.  2. Provide error checking before file operations are performed, such
  27294.     as:
  27295.  
  27296.        #define DOS_FILE_NAME_LENGTH 8
  27297.  
  27298.        if ( strlen(file_name) > DOS_FILE_NAME_LENGTH )
  27299.             printf("File name too long, try again");
  27300.  
  27301.  3. In extreme cases, you can change the constants in STDLIB.H back to
  27302.     the previous values, but this will also require the purchase of the
  27303.     Microsoft C run-time library source code so that you may rebuild
  27304.     the affected modules in the run-time library. The one advantage of
  27305.     this method is that it saves the memory used by buffers declared
  27306.     with the larger values (840 bytes).
  27307.  
  27308.  The sample program below prompts for a filename to be input. If the
  27309.  input file specification is
  27310.  
  27311.     C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
  27312.  
  27313.  then the output with C version 5.10 will be
  27314.  
  27315.      Old path was : C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
  27316.      Drive is     : C:
  27317.      Dir is       : \PATHPATHPATH\
  27318.      Fname is     : NAMENAME
  27319.      Extension is : .EXT
  27320.      New path is  : C:\PATHPATHPATH\NAMENAME.EXT
  27321.  
  27322.  while, with C version 6.00, the ouput will be:
  27323.  
  27324.      Old path was : C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
  27325.      Drive is     : C:
  27326.      Dir is       : \PATHPATHPATH\
  27327.      Fname is     : NAMENAMENAME
  27328.      Extension is : .EXTEXT
  27329.      New path is  : C:\PATHPATHPATH\NAMENAMENAME.EXTEXT
  27330.  
  27331.  Notice that in C 5.10, the name is truncated to eight characters and
  27332.  the extension is truncated to three characters (plus the period),
  27333.  while in C 6.00 the name and extension are left unchanged.
  27334.  
  27335.  Note that these same new larger constants are present in QuickC
  27336.  beginning with versions 2.50 and 2.51 because these packages share
  27337.  the same include files as C 6.00.
  27338.  
  27339.  Sample Code
  27340.  -----------
  27341.  
  27342.  /* Compile options needed: none
  27343.  */
  27344.  #include <stdio.h>
  27345.  #include <stdlib.h>
  27346.  
  27347.  void main( void)
  27348.  {
  27349.     char oldpath[_MAX_PATH];
  27350.     char newpath[_MAX_PATH];
  27351.     char   drive[_MAX_DRIVE];
  27352.     char     dir[_MAX_DIR];
  27353.     char   fname[_MAX_FNAME];
  27354.     char     ext[_MAX_EXT];
  27355.  
  27356.     printf( "Enter a file name: " );
  27357.     gets( oldpath );
  27358.  
  27359.     _splitpath( oldpath, drive, dir, fname, ext );
  27360.     _makepath( newpath, drive, dir, fname, ext );
  27361.  
  27362.     printf( "Old path was : %s\n", oldpath);
  27363.     printf( "Drive is     : %s\n", drive);
  27364.     printf( "Dir is       : %s\n", dir);
  27365.     printf( "Fname is     : %s\n", fname);
  27366.     printf( "Extension is : %s\n", ext);
  27367.     printf( "New path is  : %s\n", newpath);
  27368.  }
  27369.  
  27370.  
  27371.  590. CHRTDEMO Example Gives C2059 Error with ANSI Compatibility Set
  27372.  
  27373.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27374.  Operating System:   MS-DOS     | OS/2
  27375.  Flags: ENDUSER | s_quickc chartdemo pgchart
  27376.  Last Modified: 25-FEB-1991    ArticleIdent: Q69350
  27377.  
  27378.  If the C version 6.00 sample Presentation Graphics program CHRTDEMO.C
  27379.  is compiled with the ANSI compatibility switch (/Za), the following
  27380.  compiler error will be produced:
  27381.  
  27382.     chrtdemo.h(140) : error C2059: syntax error : '*'
  27383.  
  27384.  This is correct behavior due to the use of the Microsoft extension
  27385.  "far" found on line 140 of CHRTDEMO.H; /Za disables extensions
  27386.  specific to Microsoft C.
  27387.  
  27388.  The supplied CHRTDEMO.MAK makefile is set up to use the default
  27389.  setting of /Ze (Microsoft C extensions enabled). The C2059 error will
  27390.  only occur if this option is changed to /Za (ANSI compatibility --
  27391.  Microsoft C extensions disabled). This change could be made either
  27392.  inside the Programmer's WorkBench from the C Compiler Options dialog
  27393.  box or by actually modifying the makefile to include /Za in the
  27394.  compiler flags macro.
  27395.  
  27396.  According to the ANSI specification, all keywords that are extensions
  27397.  to the language must begin with a leading underscore. Beginning with C
  27398.  version 6.00, the Microsoft supplied header files contain this change
  27399.  to all keywords, such as _far, _pascal, etc., but the previous
  27400.  versions of these keywords without the leading underscores are
  27401.  retained for backwards compatibility.
  27402.  
  27403.  Most of the sample programs were modified to include the new keywords,
  27404.  but the line in CHRTDEMO.H was not changed to include _far, instead of
  27405.  far, thus resulting in the C2059 error with /Za. If you modify the far
  27406.  keyword on line 140 of CHRTDEMO.H so that it includes a leading
  27407.  underscore, this will eliminate the C2059 error even when /Za is
  27408.  specified.
  27409.  
  27410.  The QuickC compiler shares the same ANSI compatibility mode as the
  27411.  optimizing compiler, as well as a similar chart example program. Thus,
  27412.  the same C2059 error may be encountered with /Za in QuickC versions
  27413.  2.00, 2.01, 2.50, and 2.51.
  27414.  
  27415.  
  27416.  591. Dividing Negative Integers May Give Positive Results
  27417.  
  27418.  Product Version(s): 5.10 6.00 6.00a | 5.10 6.00 6.00a
  27419.  Operating System:   MS-DOS          | OS/2
  27420.  Flags: ENDUSER | buglist5.10 buglist6.00 buglist6.00a
  27421.  Last Modified: 30-JAN-1991    ArticleIdent: Q67740
  27422.  
  27423.  In some situations, dividing a negative integer by a positive integer
  27424.  may give positive results. For example, when the following code is
  27425.  compiled with the /Od option, both printf() statements will generate
  27426.  positive answers.
  27427.  
  27428.  Code Example
  27429.  ------------
  27430.  
  27431.  void foo(void)
  27432.  {
  27433.      int num1 = -32768,
  27434.          num2 = -32751;
  27435.  
  27436.      printf(" %d ",  num1 / 16);
  27437.      printf(" %d ", (num2 & 0xfff0) / 16);
  27438.  }
  27439.  
  27440.  When these calculations are performed, the sign bit is lost. The
  27441.  output is incorrect for the first printf() statement when -32768 is
  27442.  being divided by a power of 2 (for example, 4,8,16,32,64,...16384).
  27443.  
  27444.  Workarounds for the first printf() statement are:
  27445.  
  27446.  1. Compile without the /Od option.
  27447.  
  27448.  2. Compile with the /qc option.
  27449.  
  27450.  With the second printf(), the value (num2 & 0xfff0) must be typecast
  27451.  to an integer or separated into another statement. For example,
  27452.  
  27453.     printf(" %d ", (int)(num2 & 0xfff0) / 16);
  27454.  
  27455.  -or-
  27456.  
  27457.     num3 = num2 & 0xfff0;
  27458.     printf(" %d ", num3 / 16);
  27459.  
  27460.  Microsoft has confirmed this to be a problem in the C versions 5.10,
  27461.  6.00, and 6.00a. We are researching this problem and will post new
  27462.  information here as it becomes available.
  27463.  
  27464.  
  27465.  592. C1001: Internal Compiler Error: grammar.c, Line 140
  27466.  
  27467.  Product Version(s): 6.00a  | 6.00a
  27468.  Operating System:   MS-DOS | OS/2
  27469.  Flags: ENDUSER | buglist6.00a
  27470.  Last Modified: 31-JAN-1991    ArticleIdent: Q67781
  27471.  
  27472.  The C version 6.00a compiler produces the following internal compiler
  27473.  error when the sample program below is compiled the /Ox or /Oe
  27474.  optimizations:
  27475.  
  27476.     foo.c(9):fatal error C1001:Internal Compiler Error
  27477.         (compiler file '../grammar.c', line 140)
  27478.         Contact Microsoft Product Support Services
  27479.  
  27480.  The following are valid workarounds for this problem:
  27481.  
  27482.  1. Compile with any optimization not containing /Oe.
  27483.  
  27484.  2. Disable the "e" optimization using the optimize pragma.
  27485.  
  27486.  Sample Code
  27487.  -----------
  27488.  
  27489.  1  typedef struct utype { char bitmap[10]; } Utype;
  27490.  2  extern Utype utypes[];
  27491.  3
  27492.  4  void InitializeBitmaps(void)
  27493.  5  {
  27494.  6     int cnt,cnt2;
  27495.  7     for(cnt=0;cnt<13;cnt++)
  27496.  8       for(cnt2=0;cnt2<10;cnt2++)
  27497.  9          utypes[cnt].bitmap[cnt2]=(char)~utypes[cnt].bitmap[cnt2];
  27498.  10 }
  27499.  
  27500.  Microsoft has confirmed this to be a problem in Microsoft C version
  27501.  6.00a. We are researching this problem and will post new information
  27502.  here as it becomes available.
  27503.  
  27504.  
  27505.  593. C1001: Internal Compiler Error: regMD.c, Lines 3101 and 3074
  27506.  
  27507.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27508.  Operating System:   MS-DOS     | OS/2
  27509.  Flags: ENDUSER | buglist6.00 buglist6.00a
  27510.  Last Modified: 25-FEB-1991    ArticleIdent: Q69413
  27511.  
  27512.  The Microsoft C Compiler versions 6.00 and 6.00a produce the following
  27513.  internal compiler errors when the sample program below is compiled
  27514.  with default optimization:
  27515.  
  27516.  With C 6.00a
  27517.  ------------
  27518.  
  27519.     file.c(5) : fatal error C1001: Internal Compiler Error
  27520.                 (compiler file '@(#)regMD.c:1.110', line 3101)
  27521.                 Contact Microsoft Product Support Services
  27522.  
  27523.  With C 6.00
  27524.  -----------
  27525.  
  27526.     file.c(5) : fatal error C1001: Internal Compiler Error
  27527.                 (compiler file '@(#)regMD.c:1.100', line 3074)
  27528.                 Contact Microsoft Product Support Services
  27529.  
  27530.  These errors will occur under any memory model when using any one of
  27531.  the following optimizations (although the errors may not occur when
  27532.  some of these options are combined):
  27533.  
  27534.     /Oa, /Oc, /Od, /Oi, /On, /Op, /Or, /Os, /Ot, /Ow, or /Oz
  27535.  
  27536.  There are several possible ways to work around these errors:
  27537.  
  27538.  1. Do not use any of the above options and do not use the default
  27539.     optimization for the module where the error occurs.
  27540.  
  27541.  2. Add /Oe or /Og; one of these combined with other optimizations
  27542.     may eliminate the problem.
  27543.  
  27544.  3. Selectively disable optimizations for the particular function that
  27545.     is producing the error through use of the optimize pragma.
  27546.  
  27547.  4. Rewrite the statement to use an if-else construct instead of the
  27548.     ternary operator.
  27549.  
  27550.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  27551.  6.00a. We are researching this problem and will post new information
  27552.  here as it becomes available.
  27553.  
  27554.  Sample Code
  27555.  -----------
  27556.  
  27557.  /* Compile options needed: none
  27558.  */
  27559.  
  27560.  void func(unsigned char uch1, unsigned char uch2)
  27561.  {
  27562.      uch2 = uch1 ? (unsigned char)'0' : (unsigned char)(uch1 % 24);
  27563.  }
  27564.  
  27565.  
  27566.  594. Old Compiler Pass May Cause C1007: Unrecognized Flag -Bm in P2
  27567.  
  27568.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27569.  Operating System:   MS-DOS     | OS/2
  27570.  Flags: ENDUSER |
  27571.  Last Modified: 25-FEB-1991    ArticleIdent: Q69474
  27572.  
  27573.  If you receive the following error when compiling a program with C
  27574.  version 6.00 or 6.00a
  27575.  
  27576.     fatal error C1007: unrecognized flag '-Bm' in 'p2'
  27577.  
  27578.  it may be the result of inadvertently invoking pass 2 (C2.EXE) of an
  27579.  earlier version of the compiler, such as C version 5.10. Beginning
  27580.  with C version 6.00, the option -Bm is a valid flag for pass 2 of the
  27581.  compiler. This was not a valid option in earlier compiler versions.
  27582.  
  27583.  When looking for an executable file, the operating system will first
  27584.  search your current directory, and then search all the directories
  27585.  listed in your path. You should make sure that the C 6.00 compiler is
  27586.  listed first on your path, before any other versions of the compiler.
  27587.  This is especially true when running on a network because network
  27588.  search paths sometimes obscure exactly what directories are being
  27589.  searched for files.
  27590.  
  27591.  If you would like to double-check which drive and directory are being
  27592.  used when compiling, invoke the compiler with the /d option. This
  27593.  option displays the information that is being passed to each phase of
  27594.  the compiler, including the name and directory of the compiler file in
  27595.  use.
  27596.  
  27597.  
  27598.  595. _getpixel() Return Value is Not Changed by _setbkcolor() Call
  27599.  
  27600.  Product Version(s): 5.10 6.00 6.00a
  27601.  Operating System:   MS-DOS
  27602.  Flags: ENDUSER | s_quickc
  27603.  Last Modified:  6-FEB-1991    ArticleIdent: Q67759
  27604.  
  27605.  In the sample program below, _getpixel() will return a 0 (zero).
  27606.  Setting _setbkcolor() to any other color has no effect on the return
  27607.  value from _getpixel().
  27608.  
  27609.  The _getpixel() function is documented as returning a color index for
  27610.  a specific pixel. In the example program, there are no colors on the
  27611.  screen except the background color (color index 0). When the call to
  27612.  _setbkcolor() is made, the color mapped to index 0 is changed;
  27613.  however, the color index for the pixel is not changed. Therefore,
  27614.  _getpixel() still returns 0. This same behavior is exhibited when
  27615.  using the _remappallette() function on index 0 and the
  27616.  _remapallpallette() function.
  27617.  
  27618.  To change the color index at a particular point on the screen, first
  27619.  call the _setcolor() function with the desired color index, then use
  27620.  one of the graphics drawing functions, for example, _floodfill(),
  27621.  _setpixel(), etc.
  27622.  
  27623.  Sample Code
  27624.  -----------
  27625.  
  27626.  // Note: C 5.10 doesn't support _MAXRESMODE
  27627.  
  27628.  #include<graph.h>
  27629.  #include<stdio.h>
  27630.  void main(void)
  27631.  {
  27632.     short xvar=100,yvar=100,result1=0,result2=0;
  27633.     _setvideomode(_MAXRESMODE);
  27634.     result1=_getpixel(xvar,yvar);
  27635.     _setbkcolor(_BLUE);
  27636.     result2=_getpixel(xvar,yvar);
  27637.     _setvideomode(_DEFAULTMODE);
  27638.     printf("Before _setbkcolor - %d\n",result1);
  27639.     printf("After _setbkcolor  - %d\n",result2);
  27640.  }
  27641.  
  27642.  
  27643.  596. stdout/stderr Are Buffered When Stack Is Moved Out of DGROUP
  27644.  
  27645.  Product Version(s): 6.00 6.00a
  27646.  Operating System:   MS-DOS
  27647.  Flags: ENDUSER | buglist6.00 buglist6.00a
  27648.  Last Modified: 25-FEB-1991    ArticleIdent: Q69476
  27649.  
  27650.  By following the instructions in the C 6.00 STARTUP.DOC file, you can
  27651.  recompile/reassemble the C start-up code and modify existing libraries
  27652.  so that the stack will be moved out of DGROUP for programs linked with
  27653.  these modified libraries. When using the DOS version of these modified
  27654.  libraries, stdout and stderr are unexpectedly buffered. The sample
  27655.  code and sample output below illustrate this problem.
  27656.  
  27657.  The OS/2 versions of the modified libraries perform as expected;
  27658.  however, to achieve the correct behavior with the DOS versions of the
  27659.  modified libraries, you must add the following line to your code:
  27660.  
  27661.     setvbuf(stdout, NULL, _IONBF, 0);
  27662.  
  27663.  This line sets buffering for streams to none.
  27664.  
  27665.  Information about the predefined stream pointers can be observed by
  27666.  compiling the start-up code with CodeView information and placing a
  27667.  watch on the _iob2 array. Information about stdout is in _iob2[1].
  27668.  After executing the start-up code, the buffer size on stdout is still
  27669.  0 (zero); however, once a function call is made to printf(), the
  27670.  buffer size for _iob2[1] is changed to 512 (0x200) bytes. This change
  27671.  does not occur when the stack is left in DGROUP.
  27672.  
  27673.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  27674.  6.00a. We are researching this problem and will post new information
  27675.  here as it becomes available.
  27676.  
  27677.  Sample Code
  27678.  -----------
  27679.  
  27680.  /* Compile options needed: /c /ALw /Zi /Od
  27681.        Link options needed: /CO /NOD (plus you must specify the
  27682.                             modified DOS C run-time library)
  27683.  */
  27684.  
  27685.  #include <stdio.h>
  27686.  
  27687.  int number;
  27688.  
  27689.  void main(void)
  27690.  {
  27691.      /* Uncomment the following line to obtain the desired results */
  27692.      /* setvbuf(stdout, NULL, _IONBF, 0); */
  27693.  
  27694.      printf("\nEnter a number: ");
  27695.      scanf("%d", &number);
  27696.      printf("\nThe number is %1d\n", number);
  27697.  }
  27698.  
  27699.  Program Output
  27700.  --------------
  27701.  
  27702.  22                   /* user enters a number (without prompt) */
  27703.  
  27704.  Enter a number:      /* printf() output is buffered, so output does */
  27705.  The number is 22     /* not appear until exit code flushes buffers  */
  27706.  
  27707.  
  27708.  597. _bios_disk() May Require 3 Tries for Drive to Get Up to Speed
  27709.  
  27710.  Product Version(s): 4.00 5.00 5.10 6.00 6.00a
  27711.  Operating System:   MS-DOS
  27712.  Flags: ENDUSER |
  27713.  Last Modified: 25-FEB-1991    ArticleIdent: Q69504
  27714.  
  27715.  The _bios_disk() routine in the C run-time library uses BIOS interrupt
  27716.  0x13 to provide several disk-access functions. The ROM BIOS does not
  27717.  automatically wait for the drive to come up to speed before attempting
  27718.  to read the sector, verify the sector, or write to the sector. In the
  27719.  book "IBM ROM BIOS" by Ray Duncan, the recommendation given in each
  27720.  case is to reset the floppy disk system and try the operation three
  27721.  times before assuming an error has occurred.
  27722.  
  27723.  The following sample program from the C 6.00 online help makes three
  27724.  attempts to read the disk before giving up. A printf() statement is
  27725.  added to show which read attempt is successful.
  27726.  
  27727.  Sample Code
  27728.  -----------
  27729.  
  27730.  /* Compile options needed: none
  27731.  */
  27732.  
  27733.  #include <stdio.h>
  27734.  #include <conio.h>
  27735.  #include <bios.h>
  27736.  #include <dos.h>
  27737.  #include <stdlib.h>
  27738.  
  27739.  char _far diskbuf[512];
  27740.  
  27741.  void main( int argc, char *argv[] )
  27742.  {
  27743.     int count;
  27744.     unsigned status = 0, i;
  27745.     struct diskinfo_t di;
  27746.     struct diskfree_t df;
  27747.     unsigned char _far *p, linebuf[17];
  27748.  
  27749.     if( argc != 5 )
  27750.     {
  27751.        printf("  SYNTAX: DISK <driveletter> <head> <track> <sector>");
  27752.        exit( 1 );
  27753.     }
  27754.  
  27755.     if( (di.drive = toupper( argv[1][0] ) - 'A' ) > 1 )
  27756.     {
  27757.        printf( "Must be floppy drive" );
  27758.        exit( 1 );
  27759.     }
  27760.  
  27761.     di.head   = atoi( argv[2] );
  27762.     di.track   = atoi( argv[3] );
  27763.     di.sector   = atoi( argv[4] );
  27764.     di.nsectors = 1;
  27765.     di.buffer   = diskbuf;
  27766.  
  27767.     // Get information about disk size.
  27768.  
  27769.     if( _dos_getdiskfree( di.drive + 1, &df ) )
  27770.        exit( 1 );
  27771.  
  27772.     // Try reading disk three times before giving up.
  27773.  
  27774.     for( count = 1; count <= 3; count++ )
  27775.     {
  27776.        status = _bios_disk( _DISK_READ, &di ) >> 8;
  27777.        if( !status )
  27778.           break;
  27779.     }
  27780.  
  27781.     // Display one sector.
  27782.     if( status )
  27783.        printf( "Error: 0x%.2x\n", status );
  27784.     else
  27785.     {
  27786.        for(p=diskbuf, i=0; p < (diskbuf+df.bytes_per_sector); p++)
  27787.        {
  27788.           linebuf[i++] = (*p > 32) ? *p : '.';
  27789.           printf( "%.2x ", *p );
  27790.           if( i == 16 )
  27791.           {
  27792.              linebuf[i] = '\0';
  27793.              printf( " %16s\n", linebuf );
  27794.              i = 0;
  27795.           }
  27796.        }
  27797.     }
  27798.  
  27799.     // Which attempt was successful?
  27800.  
  27801.     printf( "\nThat was try #%d.\n", count );
  27802.  
  27803.     exit( 1 );
  27804.  }
  27805.  
  27806.  
  27807.  598. C Compiler May Give Wrong Line Number for a C2125 Error
  27808.  
  27809.  Product Version(s): 5.10 6.00 6.00a | 5.10 6.00 6.00a
  27810.  Operating System:   MS-DOS          | OS/2
  27811.  Flags: ENDUSER | buglist5.10 buglist6.00 buglist6.00a
  27812.  Last Modified: 25-FEB-1991    ArticleIdent: Q69538
  27813.  
  27814.  The C compiler will correctly produce a "C2125: allocation exceeds
  27815.  64K" error for an array larger than 64K that is not declared as huge
  27816.  or compiled for the huge memory model. However, the line number that
  27817.  the compiler displays for the error is incorrect. The sample program
  27818.  below demonstrates this problem.
  27819.  
  27820.  The following error message shows the incorrect line number generated
  27821.  when the sample code below is compiled with C version 5.10, 6.00, or
  27822.  6.00a:
  27823.  
  27824.     file.c(7) : error C2125: 'array' : allocation exceeds 64K
  27825.  
  27826.  The error is actually generated because of the array declaration on
  27827.  line 4, but the compiler always lists the line with the opening brace
  27828.  for the main() function as the location of the error (line 7 in this
  27829.  case).
  27830.  
  27831.  When the quick compile (/qc) option is specified under C 6.00 or
  27832.  6.00a, the correct line number (line 4) is generated in the error
  27833.  message:
  27834.  
  27835.     test.c(4) : error C2125: 'array' : allocation exceeds 64K
  27836.  
  27837.  Note that if you are compiling inside the Programmer's WorkBench
  27838.  (PWB), the incorrect line number in the error message will cause PWB
  27839.  to take you to an incorrect line in the source code when the compiler
  27840.  errors are displayed.
  27841.  
  27842.  Microsoft has confirmed this to be a problem in C versions 5.10, 6.00,
  27843.  and 6.00a. We are researching this problem and will post new
  27844.  information here as it becomes available.
  27845.  
  27846.  Sample Code
  27847.  -----------
  27848.  
  27849.  /* Compile options needed: none
  27850.  */
  27851.  
  27852.  char array[100000];  /* Error should be generated for this line (4) */
  27853.  
  27854.  void main(void)
  27855.  {                    /* Error message refers to this line (7) */
  27856.  }
  27857.  
  27858.  
  27859.  599. _cexit() Does Not Close Files Correctly
  27860.  
  27861.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  27862.  Operating System:   MS-DOS     | OS/2
  27863.  Flags: ENDUSER | s_quickc buglist6.00 buglist6.00a
  27864.  Last Modified: 25-FEB-1991    ArticleIdent: Q69539
  27865.  
  27866.  As stated in the online help, the _cexit() function performs clean-up
  27867.  operations and returns without terminating the process. The _cexit()
  27868.  function first calls the functions registered by the atexit() and
  27869.  onexit() routines, and then it should flush all I/O buffers and close
  27870.  all open files before returning.
  27871.  
  27872.  The _cexit() function works as described except that it does not close
  27873.  all the open files. The sample code below demonstrates this problem.
  27874.  
  27875.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  27876.  6.00a. We are researching this problem and will post new information
  27877.  here as it becomes available.
  27878.  
  27879.  Sample Code
  27880.  -----------
  27881.  
  27882.  *\
  27883.  
  27884.  #include<stdio.h>
  27885.  #include<stdlib.h>
  27886.  #include<process.h>
  27887.  
  27888.  void foo(void);
  27889.  
  27890.  void main(void)
  27891.  {
  27892.      FILE *outfile;
  27893.      int   retval;
  27894.  
  27895.      atexit(foo);    /* set up function to invoke on exit */
  27896.  
  27897.      if ( (outfile = fopen("TEST.TXT", "w")) == NULL )
  27898.          {
  27899.          printf("Could not open test file TEST.TXT");
  27900.          exit(-1);
  27901.          }
  27902.  
  27903.      retval = fprintf(outfile, "This is line 1.\n");
  27904.      if ( retval >= 0 )
  27905.          printf("\nFirst line written successfully to file.\n");
  27906.      else
  27907.          printf("\nFile write failed on first attempt!\n");
  27908.  
  27909.      _cexit();   /* Call _cexit() -- files should all be closed */
  27910.  
  27911.      retval = fprintf(outfile, "This line should not be written!\n");
  27912.      if ( retval >= 0 )
  27913.          printf("Error - Write to file succeeded for file that should"
  27914.                 " have been closed!\n");
  27915.      else
  27916.          printf("File write failed on second attempt as expected!\n");
  27917.  
  27918.      fclose(outfile);
  27919.  }
  27920.  
  27921.  void foo(void)
  27922.  {
  27923.      printf("\nThis is the exit function code.\n\n");
  27924.  }
  27925.  
  27926.  
  27927.  600. Local Variable Allocation Is Limited to 32K
  27928.  
  27929.  Product Version(s): 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  27930.  Operating System:   MS-DOS                    | OS/2
  27931.  Flags: ENDUSER | s_quickc stack
  27932.  Last Modified: 15-JAN-1991    ArticleIdent: Q19785
  27933.  
  27934.  The total amount of space that can be allocated for variables local to
  27935.  a function is 32K. Trying to allocate more than this will result in
  27936.  the following compiler error:
  27937.  
  27938.     fatal error C1126: automatic allocation exceeds 32K
  27939.  
  27940.  
  27941.  601. GRAPHICS.LIB Cannot Be Used with Tiny Model
  27942.  
  27943.  Product Version(s): 6.00 6.00a
  27944.  Operating System:   MS-DOS
  27945.  Flags: ENDUSER | s_quickc s_quickasm
  27946.  Last Modified:  6-FEB-1991    ArticleIdent: Q67761
  27947.  
  27948.  Programs written in the tiny model cannot use the graphics library
  27949.  supplied with Microsoft C versions 6.00 and 6.00a. The graphics
  27950.  routines are meant to be model-independent, so they are labeled as far
  27951.  procedures. The linker does not allow far references in a tiny model
  27952.  program and does not resolve the references to the graphics routines.
  27953.  
  27954.  The sample source code below demonstrates this problem. The program
  27955.  should be compiled with:
  27956.  
  27957.     cl /AT foo.c graphics.lib
  27958.  
  27959.  For more information on building .COM files, query on the article
  27960.  titled "Use of _far Keyword in Tiny Programs."
  27961.  
  27962.  Sample Code
  27963.  -----------
  27964.  
  27965.  #include <graph.h>
  27966.  
  27967.  void main(void);
  27968.  
  27969.  void main()
  27970.  {
  27971.     _setvideomode(_DEFAULTMODE);
  27972.  }
  27973.  
  27974.  
  27975.  602. C1001: Internal Compiler Error: regMD.c, Line 1017
  27976.  
  27977.  Product Version(s): 6.00a  | 6.00a
  27978.  Operating System:   MS-DOS | OS/2
  27979.  Flags: ENDUSER | buglist6.00a
  27980.  Last Modified: 28-DEC-1990    ArticleIdent: Q67778
  27981.  
  27982.  When compiling with /Oe optimization under the compact or large memory
  27983.  models, the code below generates the following internal compiler error
  27984.  with Microsoft C version 6.00a:
  27985.  
  27986.     fatal error c1001: Internal Compiler Error
  27987.          (compiler file '@(#)regMD.c:1.110',line 1017)
  27988.          Contact Microsoft Product Support Services
  27989.  
  27990.  Sample Code
  27991.  -----------
  27992.  
  27993.      char hex_digits[]={"f"};
  27994.  
  27995.      int x(char *resultp, int item)
  27996.      {
  27997.          char *s;
  27998.          int hundreds;
  27999.  
  28000.          s=resultp;
  28001.          hundreds=100;
  28002.          if(hundreds)
  28003.            *s++='0';
  28004.          *s++=' ';
  28005.          *s++=hex_digits[item/16];
  28006.          *s++=hex_digits[item%16];
  28007.      }
  28008.  
  28009.  The following are valid workarounds for the problem:
  28010.  
  28011.  1. Compile without the /Oe optimization.
  28012.  
  28013.  2. Use the #pragma optimize switch in the code to turn off the
  28014.     offending optimizations for the particular function.
  28015.  
  28016.  3. Compile under the small or medium memory models.
  28017.  
  28018.  
  28019.  603. Jumping into the Middle of a For Loop Is Not Recommended
  28020.  
  28021.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  28022.  Operating System:   MS-DOS                         | OS/2
  28023.  Flags: ENDUSER | s_quickc
  28024.  Last Modified: 15-JAN-1991    ArticleIdent: Q19972
  28025.  
  28026.  Question:
  28027.  
  28028.  Under what conditions can a program perform a jump (via goto) into the
  28029.  middle of a for loop?
  28030.  
  28031.  Response:
  28032.  
  28033.  The only restriction on the goto statement is that the goto statement
  28034.  and its corresponding label be located in the same function. However,
  28035.  because different compilers optimize for loops differently, using a
  28036.  goto to jump into the middle of a for loop is not considered safe or
  28037.  portable.
  28038.  
  28039.  Also, if you are jumping into an inner loop that uses auto variables,
  28040.  an additional problem may occur because different compilers allocate
  28041.  space for auto variables in loops in different ways.
  28042.  
  28043.  Essentially, it is risky and not advisable for a program to jump into
  28044.  the middle of a for loop.
  28045.  
  28046.  
  28047.  604. No More Than 255 Modules May Be Placed in Overlays
  28048.  
  28049.  Product Version(s): 4.00 5.00 5.10 6.00 6.00a
  28050.  Operating System:   MS-DOS
  28051.  Flags: ENDUSER |  s_quickc s_link
  28052.  Last Modified: 15-JAN-1991    ArticleIdent: Q22286
  28053.  
  28054.  Question:
  28055.  
  28056.  The "too many overlays" error message indicates that my program
  28057.  defines more than 63 overlays. Is there also a limitation on the
  28058.  number of total modules that can be in overlays?
  28059.  
  28060.  I have a large C program that contains more than 255 modules in a
  28061.  total of 12 overlays. I receive no error messages, however, my link
  28062.  map indicates that all modules after the 255th are placed in the root
  28063.  instead of the overlays I specified.
  28064.  
  28065.  Response:
  28066.  
  28067.  There is a limit of 255 code segments that can be overlayed. Segments
  28068.  beyond this limit are put in the root.
  28069.  
  28070.  
  28071.  605. The Most Common C Programming Errors
  28072.  
  28073.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  28074.  Operating System:   MS-DOS                         | OS/2
  28075.  Flags: ENDUSER | s_quickc
  28076.  Last Modified: 15-JAN-1991    ArticleIdent: Q22321
  28077.  
  28078.  The following is a list of the most common C programming errors. Any
  28079.  of these items could cause unpredictable results, such as trashed data
  28080.  or a system hang.
  28081.  
  28082.   1. Using auto variables that have not been initialized.
  28083.  
  28084.   2. Leaving out the closing comment delimiter.
  28085.  
  28086.   3. Over-indexing an array.
  28087.  
  28088.   4. Leaving out a semicolon (;) or brace ({}).
  28089.  
  28090.   5. Using uninitialized pointers.
  28091.  
  28092.   6. Using break with an IF block, since break does not exit out of IF
  28093.      blocks. It only breaks you out of WHILE, FOR, or SWITCH loops.
  28094.  
  28095.   7. Comparing a char variable against EOF, as in the following
  28096.      example:
  28097.  
  28098.         char c;
  28099.         while ((c=getchar()) != EOF)
  28100.             {
  28101.             }
  28102.  
  28103.      If c is a char, you cannot test c against EOF because a -1 cannot
  28104.      fit into a character, so c must be an int.
  28105.  
  28106.   8. Using a forward slash instead of a backslash (for example, /n
  28107.      instead of \n).
  28108.  
  28109.   9. Using = instead of == in a comparison.
  28110.  
  28111.  10. Overwriting the null terminator (the last byte) in a string by
  28112.      indexing 1 byte too far.
  28113.  
  28114.  11. Placing a semicolon improperly, as in the following example:
  28115.  
  28116.         void foo(int a,char b);   /* semicolon does not belong here */
  28117.         {  }
  28118.  
  28119.  12. Forgetting that scanf() expects addresses.
  28120.  
  28121.  13. Using the wrong return value for a function. For example, a
  28122.      function that returns a real, but is not declared, will return an
  28123.      int by default.
  28124.  
  28125.  14. Using expressions with side effects. For example, a[i] = i++; is
  28126.      ambiguous.
  28127.  
  28128.  15. Forgetting that static variables inside functions are initialized
  28129.      only once.
  28130.  
  28131.  16. Unintentionally omitting a break from a case label in a switch
  28132.      statement, and therefore, falling through to the next case.
  28133.  
  28134.  
  28135.  606. Internal Representation for NAN or INF Is Coprocessor Specific
  28136.  
  28137.  Product Version(s): 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  28138.  Operating System:   MS-DOS               | OS/2
  28139.  Flags: ENDUSER | 8087 80x87 80287 80387
  28140.  Last Modified: 15-JAN-1991    ArticleIdent: Q22320
  28141.  
  28142.  The internal representation for a NAN (Not A Number) or INF (Infinity)
  28143.  is coprocessor dependent. To obtain this information, we recommend
  28144.  that you consult the "Numeric Supplement" in the "Intel iAPX
  28145.  Programmer's Reference Manual" for the specific coprocessor chip.
  28146.  
  28147.  
  28148.  607. "Invalid Object Module" Usually Caused by Old Version of LINK
  28149.  
  28150.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
  28151.  Operating System:   MS-DOS
  28152.  Flags: ENDUSER | s_quickc
  28153.  Last Modified:  4-DEC-1990    ArticleIdent: Q22331
  28154.  
  28155.  In many cases, an "invalid object module" error message from the
  28156.  linker indicates that an incorrect version of LINK is being utilized.
  28157.  Most DOS systems contain a DOS directory listed near the beginning of
  28158.  the PATH. Because DOS ships with a version of LINK, this version is
  28159.  often picked up instead of the correct version.
  28160.  
  28161.  To indicate if the wrong linker is the source of an "invalid object
  28162.  module" error, perform the following steps:
  28163.  
  28164.  1. Change into the language product directory where the version of
  28165.     LINK.EXE that came with the compiler you are currently using
  28166.     resides.
  28167.  
  28168.  2. Type "link" at the DOS prompt.
  28169.  
  28170.  3. The copyright banner for LINK will appear. Note the version number
  28171.     of LINK that is indicated. (This is the correct version of LINK
  28172.     that you should be using.)
  28173.  
  28174.  4. Press CTRL+C to exit out of LINK.
  28175.  
  28176.  5. Switch to the work directory where you normally compile and link
  28177.     your program.
  28178.  
  28179.  6. Perform steps 2 through 4 again.
  28180.  
  28181.  If the version of LINK that comes up in your work directory is
  28182.  different than the correct version you first noted in the language
  28183.  directory, then you have another version of LINK in a directory in
  28184.  your PATH that comes before the directory with the correct version.
  28185.  
  28186.  If you do find that you are picking up another LINK.EXE on your
  28187.  system, you will need to determine where it resides. Most likely, it
  28188.  is a DOS linker that came with the operating system because these are
  28189.  older versions of LINK that are not well-matched to the newer language
  28190.  products. Be aware, however, that it also could be the linker from
  28191.  another Microsoft language product. In either case, you should do one
  28192.  of the following to correct this problem:
  28193.  
  28194.  1. Locate the old linker and rename it to something resembling LINK.OLD.
  28195.     It is rare that you would need the DOS linker for anything, but this
  28196.     method assures that it will still be available.
  28197.  
  28198.  2. Change your path so that your PATH environment variable points
  28199.     first to the directory containing the correct version of LINK.EXE.
  28200.     This solution is less preferable than the one above because it does
  28201.     nothing to ensure that the problem will not appear again if you make
  28202.     some changes to your system.
  28203.  
  28204.  It is not uncommon to have a number of linkers in directories that are
  28205.  specified in the PATH. Therefore, it is highly recommended that you
  28206.  repeat the version number test from within your work directory once
  28207.  you have implemented one of these solutions.
  28208.  
  28209.  
  28210.  608. C1001: Internal Compiler Error: regMD.c, Lines 3047 and 3020
  28211.  
  28212.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28213.  Operating System:   MS-DOS     | OS/2
  28214.  Flags: ENDUSER | buglist6.00 buglist6.00a
  28215.  Last Modified: 31-JAN-1991    ArticleIdent: Q67779
  28216.  
  28217.  The sample code below produces the following internal compiler errors
  28218.  when compiled under different versions of the C compiler. The problem
  28219.  occurs when compiled with the /Og and /Oe optimizations under the
  28220.  compact and large memory models.
  28221.  
  28222.  Under C 6.00a
  28223.  -------------
  28224.  
  28225.     file.c(11) : fatal error C1001: Internal Compiler Error
  28226.                        (compiler file '@(#)regMD.c:1.110', line 3047)
  28227.                        Contact Microsoft Product Support Services
  28228.  
  28229.  Under C 6.00
  28230.  ------------
  28231.  
  28232.     file.c(11) : fatal error C1001: Internal Compiler Error
  28233.                        (compiler file '@(#)regMD.c:1.110', line 3020)
  28234.                        Contact Microsoft Product Support Services
  28235.  
  28236.  The following are valid workarounds for the problem:
  28237.  
  28238.  1. Compile without the /Oe or /Og optimizations.
  28239.  
  28240.  2. Use the #pragma optimize switch in the code to turn off the
  28241.     offending optimizations for the particular function.
  28242.  
  28243.  3. Compile under the small or medium memory models.
  28244.  
  28245.  Sample Code
  28246.  -----------
  28247.  
  28248.  #include<string.h>
  28249.  
  28250.  void foo (void)
  28251.  {
  28252.      char *o, *wp, *cp;
  28253.      int c,t;
  28254.  
  28255.      for (;;)
  28256.      {
  28257.          wp++;
  28258.          t = wp - cp;
  28259.          if (c) t=0;
  28260.          if (t) strncpy (&o[c], cp, t );
  28261.          c = t;
  28262.          cp = wp;
  28263.      }
  28264.  }
  28265.  
  28266.  
  28267.  609. /MT Cannot Be Mixed with /FPa As Shown on Page 370 of APT
  28268.  
  28269.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28270.  Operating System:   MS-DOS     | OS/2
  28271.  Flags: ENDUSER | docerr
  28272.  Last Modified:  6-FEB-1991    ArticleIdent: Q67782
  28273.  
  28274.  Page 370 of the "Advanced Programming Techniques" manual shipped with
  28275.  Microsoft C version 6.00 incorrectly gives an example of combining the
  28276.  command-line switches /MT and /FPa. This procedure does not work and
  28277.  will cause the compiler to generate the following error message:
  28278.  
  28279.     Command Line Error D2016: '-MT' and '-FPa' are incompatible
  28280.  
  28281.  To use the alternate math libraries, you must either create a single
  28282.  threaded .EXE or a multithreaded DLL. The libraries to create a
  28283.  multithreaded .EXE are not available.
  28284.  
  28285.  
  28286.  610. C1001: Internal Compiler Error: regMD.c, Lines 4634 and 4688
  28287.  
  28288.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28289.  Operating System:   MS-DOS     | OS/2
  28290.  Flags: ENDUSER | buglist6.00 buglist6.00a
  28291.  Last Modified:  6-FEB-1991    ArticleIdent: Q67783
  28292.  
  28293.  When compiled with /Oe and /MD, the sample code generates an internal
  28294.  compiler error for Microsoft C Compiler versions 6.00 and C 6.00a. The
  28295.  errors are different for each version.
  28296.  
  28297.  Under C 6.00
  28298.  ------------
  28299.  
  28300.     fatal error c1001: Internal Compiler Error
  28301.     (compiler file '@(#)regMD.c:1.110',line 4634)
  28302.  
  28303.  Under C 6.00a
  28304.  -------------
  28305.  
  28306.     fatal error c1001: Internal Compiler Error
  28307.     (compiler file '@(#)regMD.c:1.110',line 4688)
  28308.  
  28309.  Sample Code
  28310.  -----------
  28311.  
  28312.  char wi_lines(char);
  28313.  
  28314.  int w_hline(char *pnt)
  28315.  {
  28316.     int x;
  28317.     for (x=0;x<=10;x++)
  28318.     pnt[x]=wi_lines(pnt[x]);
  28319.  }
  28320.  
  28321.  
  28322.  611. C 6.00/6.00a May Incorrectly Generate C4009 Warning with /Zg
  28323.  
  28324.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28325.  Operating System:   MS-DOS     | OS/2
  28326.  Flags: ENDUSER | buglist6.00 buglist6.00a
  28327.  Last Modified:  6-FEB-1991    ArticleIdent: Q67784
  28328.  
  28329.  When compiling with the "/Zg" option in C version 6.00 or 6.00a, a
  28330.  C4009 (string too big, trailing characters truncated) warning error
  28331.  may be incorrectly flagged. In the sample code below, a local array of
  28332.  strings of total size greater than 2K will generate the warning. If
  28333.  the array is made global or the total size is less than 2K, the
  28334.  warning is not generated.
  28335.  
  28336.  Sample Code
  28337.  -----------
  28338.  
  28339.  void main(void) { }
  28340.  
  28341.  int test(void) {
  28342.  
  28343.  char * test_array[3][35] = {
  28344.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28345.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28346.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28347.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28348.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28349.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28350.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28351.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28352.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28353.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28354.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28355.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28356.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28357.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28358.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28359.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28360.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28361.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28362.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28363.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28364.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28365.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28366.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28367.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28368.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28369.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28370.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28371.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28372.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28373.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28374.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28375.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28376.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28377.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28378.  "xxxxxxxxxxxxxxxxxxxx","yyyyyyyyyyyyyyyyyyy","zzzzzzzzzzzzzzzzzzzz"
  28379.  };
  28380.  
  28381.  }
  28382.  
  28383.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  28384.  6.00a. We are researching this problem and will post new information
  28385.  here as it becomes available.
  28386.  
  28387.  
  28388.  612. Bit Operations on Char May Produce Unexpected Results
  28389.  
  28390.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28391.  Operating System:   MS-DOS     | OS/2
  28392.  Flags: ENDUSER | buglist6.00
  28393.  Last Modified:  6-FEB-1991    ArticleIdent: Q67785
  28394.  
  28395.  Bit manipulations on type char may produce different results depending
  28396.  on the compiler switches. The /J and /qc switches have different
  28397.  effects on the code below when using the Microsoft C versions 6.00 and
  28398.  6.00a compiler.
  28399.  
  28400.  Sample Code
  28401.  -----------
  28402.  
  28403.  #include <stdio.h>
  28404.  
  28405.  char unsigned ary[4] = {0xF6, 0xF7, 0xF8, 0xF9};
  28406.  
  28407.  void main(void)
  28408.  {
  28409.     unsigned long result1, result2;
  28410.     char *p;
  28411.     p = ary;
  28412.     result1 = *p | ( *(p+2) << 8);
  28413.     result1 += ( *(p+1) | ( *(p+3) << 8)) * 0x10000;
  28414.     result2 = (unsigned long)(( *(p+2) << 8) | *p) |
  28415.               (unsigned long)(( *(p+3) << 8) | *(p+1)) << 16;
  28416.     printf("result1 = %lX\n", result1);
  28417.     printf("result2 = %lX\n", result2);
  28418.  }
  28419.  
  28420.  When compiled with
  28421.  
  28422.     cl /qc /J foo.c
  28423.  
  28424.  the results are:
  28425.  
  28426.     result1 = F9F7F8F6
  28427.     result2 = F9F7F8F6
  28428.  
  28429.  When compiled with
  28430.  
  28431.     cl /J foo.c
  28432.  
  28433.  the results are:
  28434.  
  28435.     result1 = F9F6F8F6
  28436.     result2 = FFFFF8F6
  28437.  
  28438.  When compiled with
  28439.  
  28440.     cl /qc foo.c
  28441.  or
  28442.     cl foo.c
  28443.  
  28444.  the results are:
  28445.  
  28446.     result1 = FFF6FFF6
  28447.     result2 = FFFFFFF6
  28448.  
  28449.  The differences occur because of a problem in the Quick Compiler. When
  28450.  an integral promotion is required, the Quick Compiler incorrectly
  28451.  converts an unsigned char to an unsigned int. According to ANSI, if
  28452.  all the values of a char can be represented in an int, it is converted
  28453.  to an int; otherwise, it is converted to an unsigned int (see section
  28454.  3.2.1.1). This is also documented in the "Advanced Programming
  28455.  Techniques" manual on page 422.
  28456.  
  28457.  There are a number of ways to work around this problem depending on
  28458.  the desired results. If the intent was to generate results equal to
  28459.  F9F7F8F6 (as the Quick Compiler with /J did), declare "p" as a pointer
  28460.  to an unsigned char and modify the equations for "result1" and
  28461.  "result2" to use unsigned int casts where appropriate. For example:
  28462.  
  28463.     result1 = *p | ((unsigned int)*(p+2) << 8);
  28464.     result1 += ( *(p+1) | ( *(p+3) << 8)) * 0x10000;
  28465.  
  28466.  -or-
  28467.  
  28468.     result2 = ((unsigned long)(((unsigned int)*(p+2) << 8) | *p)|
  28469.               (unsigned long)(( *(p+3) << 8) | *(p+1)) << 16;
  28470.  
  28471.  If the results from the full optimizing compiler with /J are desired,
  28472.  again declare "p" as a pointer to unsigned char and replace the above
  28473.  mentioned casts with signed int. Finally, if the results without /J
  28474.  are desired, declare "p" as a pointer to a signed char.
  28475.  
  28476.  Microsoft has confirmed this to be a problem in the Microsoft C
  28477.  Compiler versions 6.00 and 6.00a. We are researching this problem and
  28478.  will post new information here as it becomes available.
  28479.  
  28480.  
  28481.  613. Code Generation Error with C 6.00 and Global Variables
  28482.  
  28483.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28484.  Operating System:   MS-DOS     | OS/2
  28485.  Flags: ENDUSER | buglist6.00 buglist6.00a
  28486.  Last Modified:  6-FEB-1991    ArticleIdent: Q67786
  28487.  
  28488.  The sample program below does not compile properly when using any
  28489.  optimizations other than /Od under C versions 6.00 and 6.00a. The code
  28490.  generated by the compiler incorrectly assumes that foo and bar are
  28491.  equal after the call to the function inc_foo. The compiler then
  28492.  accesses bar[1] by using the value of foo rather than the value of
  28493.  bar. This generates the wrong effect on the array being modified.
  28494.  
  28495.  There are several workarounds:
  28496.  
  28497.  1. Use the /Od option or the /qc option.
  28498.  
  28499.  2. Declare foo as a volatile pointer to a char.
  28500.  
  28501.  3. Change the code to assign buf to bar first.
  28502.  
  28503.  Microsoft has confirmed this to be a problem in C versions 6.00 and
  28504.  6.00a. We are researching this problem and will post new information
  28505.  here as it becomes available.
  28506.  
  28507.  Sample Code
  28508.  -----------
  28509.  
  28510.  #include <stdio.h>
  28511.  char inc_foo (void);
  28512.  
  28513.  char * foo;
  28514.  char * bar;
  28515.  char * buf = "....................";
  28516.  
  28517.  main ()
  28518.  {
  28519.     foo= buf;
  28520.     bar= buf;
  28521.     bar[1]= inc_foo ();
  28522.     printf ("buf = %s\n", buf);
  28523.     printf ("foo = %d\nbar = %d\n", foo, bar);
  28524.  }
  28525.  
  28526.  char inc_foo ()
  28527.  {
  28528.     foo += 10;
  28529.     return (char) '[';
  28530.  }
  28531.  
  28532.  The correct output is:
  28533.  
  28534.  buf = .[..................
  28535.  foo = 76
  28536.  bar = 66
  28537.  
  28538.  The output generated is:
  28539.  
  28540.  buf = ...........[........
  28541.  foo = 76
  28542.  bar = 66
  28543.  
  28544.  
  28545.  614. %n Format Specifier May Be Ignored in C 6.00 sscanf()
  28546.  
  28547.  Product Version(s): 6.00 6.00a | 6.00 6.00a
  28548.  Operating System:   MS-DOS     | OS/2
  28549.  Flags: ENDUSER |
  28550.  Last Modified:  6-FEB-1991    ArticleIdent: Q67790
  28551.  
  28552.  If the "%n" format specifier is used within a sscanf() function and
  28553.  the format specifier before it causes the last character to be read
  28554.  from the string of data, the %n will be ignored and the sscanf()
  28555.  function will return without making the %n assignment. This is correct
  28556.  per ANSI specifications, since an input failure before the %n
  28557.  parameter is evaluated.
  28558.  
  28559.  The code below demonstrates the problem. Notice that the last
  28560.  parameter passed (d) does not get changed. The sscanf() statement
  28561.  finishes making assignments as soon as it reaches the end of the
  28562.  string.
  28563.  
  28564.  Sample Code
  28565.  -----------
  28566.  
  28567.  #include <stdio.h>
  28568.  
  28569.  void main(void)
  28570.  {
  28571.     int a,b,c,d;
  28572.     char buffer[50];
  28573.     a=b=c=d=0;
  28574.  
  28575.     sscanf("100Dummy2","%n%d%n%s%n",&a,&b,&c,buffer,&d);
  28576.  
  28577.     printf("%d  %d  %d\n",a,c,d);
  28578.  }
  28579.  
  28580.  Output
  28581.  ------
  28582.  
  28583.  0  3  0
  28584.  
  28585.  
  28586.  615. C and QuickC Compiler Options Should Be Placed Before .C File
  28587.  
  28588.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  28589.  Operating System:   MS-DOS                         | OS/2
  28590.  Flags: ENDUSER | s_quickc
  28591.  Last Modified:  4-DEC-1990    ArticleIdent: Q23739
  28592.  
  28593.  The C and QuickC compiler switches must be specified on the command-
  28594.  line, before any source files that the option is intended to apply to.
  28595.  In most cases, specifying options at the end of the command-line after
  28596.  a filename will NOT generate any warnings or errors -- the compiler
  28597.  will ignore the options because there are no following source files
  28598.  that the options apply to.
  28599.  
  28600.  In a few cases, a trailing option at the end of the command-line will
  28601.  generate an error if the option conflicts with a previously specified
  28602.  option.
  28603.  
  28604.  
  28605.  616. Effects of Min and Max Memory Allocation During C Program Load
  28606.  
  28607.  Product Version(s): 4.00 5.00 5.10 6.00 6.00a
  28608.  Operating System:   MS-DOS
  28609.  Flags: ENDUSER | s_quickc s_link s_exemod s_exehdr
  28610.  Last Modified:  6-FEB-1991    ArticleIdent: Q24935
  28611.  
  28612.  Changing the minimum and maximum allocation values in an .EXE file
  28613.  will affect the way in which memory is allocated for a program.
  28614.  
  28615.  Memory is dynamically allocated for a program when it is loaded. DOS
  28616.  initially attempts to allocate FFFFH paragraphs memory. This will
  28617.  always fail, returning the size of the largest free block. If this
  28618.  block is smaller than the minimum allocation and the load size, a
  28619.  no-memory error will occur. If this block is larger than the sum of
  28620.  the maximum allocation and the load size, DOS will allocate the amount
  28621.  specified by the load size and the maximum allocation. Otherwise, the
  28622.  largest block of memory available is allocated.
  28623.  
  28624.  An example of when the maximum allocation should be changed would be a
  28625.  program, such as a menu driver, that spawns other programs. Since this
  28626.  program would stay resident in memory, the maximum allocation should
  28627.  be set to the minimum allocation to keep as much memory available as
  28628.  possible for the spawned programs.
  28629.  
  28630.  In small memory model, the C start-up code will return all memory
  28631.  allocated to it back to DOS, except for a 64K block reserved for the
  28632.  default data group. If only 4K of this 64K will be used by the menu
  28633.  program, the entire 64K should not be kept. There are several ways of
  28634.  changing the maximum allocation to 4K -- you can link with the /CP:1
  28635.  option or you can modify an existing .EXE file with the EXEHDR or
  28636.  EXEMOD utilities.
  28637.  
  28638.  
  28639.  617. fseek() Function Requires a long for the Offset into a File
  28640.  
  28641.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  28642.  Operating System:   MS-DOS                         | OS/2
  28643.  Flags: ENDUSER |
  28644.  Last Modified:  6-FEB-1991    ArticleIdent: Q23753
  28645.  
  28646.  Question:
  28647.  
  28648.  I am using fseek() to seek in a file, but it fails when I try to seek
  28649.  beyond 32K. Is this a limit of fseek()?
  28650.  
  28651.  Response:
  28652.  
  28653.  The offset parameter to fseek() takes a value of type long, so this
  28654.  problem is not likely to be the result of fseek() limits. On the other
  28655.  hand, this situation does occur if you are using variables of type int
  28656.  to calculate the offset. Because an int is limited to a maximum value
  28657.  of 32,767 (32K), values assigned to ints between 32K and 64K are
  28658.  treated as negative.
  28659.  
  28660.  An int will be automatically typecast to a long when passed to fseek()
  28661.  but when this occurs, it is sign-extended. Thus, an int value above
  28662.  32K that is represented as negative will be sign-extended to a
  28663.  negative long. This, in turn, specifies a negative offset into the
  28664.  file, which fails to produce the expected results.
  28665.  
  28666.  When using the fseek() routine, just be sure to use a long for
  28667.  specifying the offset into the file.
  28668.  
  28669.  
  28670.  618. Difference Between Minimum Load Size and Minimum Allocation
  28671.  
  28672.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
  28673.  Operating System:   MS-DOS
  28674.  Flags: ENDUSER | s_quickc s_link s_exehdr s_exemod
  28675.  Last Modified:  6-FEB-1991    ArticleIdent: Q25024
  28676.  
  28677.  The following is a summation of the differences between the minimum
  28678.  load size and the minimum allocation size in a DOS executable (.EXE)
  28679.  file header:
  28680.  
  28681.  The minimum load size is the amount of memory needed for the load
  28682.  module, plus the minimum allocation value. This reflects the amount of
  28683.  memory necessary to load and run the program, assuming no dynamic
  28684.  allocation is necessary.
  28685.  
  28686.  The minimum allocation is the amount of memory needed above the actual
  28687.  load module. These values determine the highest memory location into
  28688.  which the program can be loaded. For example, if the minimum load size
  28689.  is 0, the program will be loaded at the highest possible location in
  28690.  memory.
  28691.  
  28692.  
  28693.  619. Sending 1Ah to a Printer Requires Setting "Raw" Mode
  28694.  
  28695.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
  28696.  Operating System:   MS-DOS
  28697.  Flags: ENDUSER |
  28698.  Last Modified:  4-FEB-1991    ArticleIdent: Q23867
  28699.  
  28700.  Problem:
  28701.  
  28702.  I am trying to output a graphics file to a printer. I have opened the
  28703.  printer as a binary file, but the output stops every time I try to
  28704.  output hexadecimal character 1A. I assumed that anything could be
  28705.  output to a binary file.
  28706.  
  28707.  Response:
  28708.  
  28709.  If you open a device, such as PRN, as a binary file using fopen() or
  28710.  open(), the device will not translate carriage return/line feed
  28711.  combinations. However, DOS will continue to interpret CTRL+Z (1Ah) as
  28712.  an end-of-file character.
  28713.  
  28714.  You must use interrupt 21h function 44h to set the raw-mode bit for
  28715.  the device to disable checking for CTRL+Z characters. This way, all
  28716.  characters will be allowed to pass.
  28717.  
  28718.  The following example was taken from page 351 of "Advanced MS-DOS
  28719.  Programming," which gives an assembly language program example for
  28720.  setting raw mode.
  28721.  
  28722.  Sample Code
  28723.  -----------
  28724.  
  28725.  void setrawmode(void)
  28726.  {
  28727.     union REGS inregs, outregs;
  28728.  
  28729.     inregs.x.ax = 0x4400;
  28730.     inregs.x.bx = 0x04;         /* specify the printer */
  28731.     int86(0x21, &inregs, &outregs);
  28732.  
  28733.     outregs.h.dh = 0x00;
  28734.     outregs.h.dl = 0x20;        /* set raw mode bit */
  28735.     outregs.x.ax = 0x4401;
  28736.     int86(0x21, &outregs, &inregs);
  28737.  }
  28738.  
  28739.  
  28740.  620. How to Do "Peeks" and "Pokes" in a C Program
  28741.  
  28742.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
  28743.  Operating System:   MS-DOS
  28744.  Flags: ENDUSER | s_quickc
  28745.  Last Modified:  6-FEB-1991    ArticleIdent: Q23868
  28746.  
  28747.  The sample code below contains two functions that simulate what are
  28748.  commonly known as "peek" and "poke" functions. The peek() function
  28749.  allows you to look at the contents of any memory location while the
  28750.  poke() function allows you to place a value into any memory location.
  28751.  
  28752.  Sample Code
  28753.  -----------
  28754.  
  28755.  /* The following function will stuff a value into any location in
  28756.     addressable memory. seg:ofs = val.
  28757.  */
  28758.  
  28759.  void poke(unsigned int seg, unsigned int ofs, char val)
  28760.  {
  28761.      unsigned char far *ptr;
  28762.  
  28763.      ptr = (unsigned char far *) (((long)seg<<16)|(long)ofs);
  28764.      *ptr = val;
  28765.  }
  28766.  
  28767.  /* The following function will return the contents of any location in
  28768.     addressable memory. return(seg:ofs).
  28769.  */
  28770.  
  28771.  unsigned char peek(unsigned int seg, unsigned int ofs)
  28772.  {
  28773.      unsigned char far *ptr;
  28774.  
  28775.      ptr = (unsigned char far *) (((long)seg<<16)|(long)ofs);
  28776.      return(*ptr);
  28777.  }
  28778.  
  28779.  
  28780.  621. malloc() and free() Do Not Return Memory to DOS
  28781.  
  28782.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a
  28783.  Operating System:   MS-DOS
  28784.  Flags: ENDUSER | s_quickc
  28785.  Last Modified: 15-JAN-1991    ArticleIdent: Q23869
  28786.  
  28787.  Problem:
  28788.  
  28789.  My large model program calls system() to do a directory, and then I
  28790.  malloc() a large amount of space. I can free() it all but I get a "Not
  28791.  enough memory" error when I try to call system() again. Apparently
  28792.  free() is not returning the memory to DOS.
  28793.  
  28794.  Response:
  28795.  
  28796.  When you malloc() a large amount of space (more than is available
  28797.  within the current heap), the malloc() function will execute a DOS
  28798.  call to get more memory in an attempt to expand the heap. If this is
  28799.  successful, DOS will allocate the desired memory to your program and
  28800.  malloc() will return successful. If you then free() this memory, it
  28801.  will be marked as free within your program's heap and will be
  28802.  available for use again by your program.
  28803.  
  28804.  However, DOS still sees this memory as being used by the program
  28805.  because it now resides within the program's heap. If you attempt a
  28806.  subsequent system() call, DOS may find it does not have enough free
  28807.  memory to load the code required to perform the system() function.
  28808.  
  28809.  An alternative is to use halloc() and hfree(), which will return the
  28810.  memory to DOS, rather than retaining it for use by the currently
  28811.  executing program.
  28812.  
  28813.  
  28814.  622. C 6.00a CD-ROM Setup Does Not Install RAMDRIVE or SMARTDRV
  28815.  
  28816.  Product Version(s): 6.00a  | 6.00a
  28817.  Operating System:   MS-DOS | OS/2
  28818.  Flags: ENDUSER | buglist6.00a
  28819.  Last Modified: 31-JAN-1991    ArticleIdent: Q67847
  28820.  
  28821.  When Setup is run from the CD-ROM version of Microsoft C version
  28822.  6.00a, the following two files are not found along the specified path:
  28823.  
  28824.     \HD525\DISK7\RAMDRIVE.SYS
  28825.     \HD525\DISK7\SMARTDRV.SYS
  28826.  
  28827.  The two files are included in this path:
  28828.  
  28829.     \HD525\DISK6\RAMDRIVE.SYS
  28830.     \HD525\DISK6\SMARTDRV.SYS
  28831.  
  28832.  Since the files are not compressed, they can be copied to your hard
  28833.  drive.
  28834.  
  28835.  Microsoft has confirmed this to be a problem in the C version 6.00a
  28836.  CD-ROM Setup program. We are researching this problem and will post
  28837.  new information here as it becomes available.
  28838.  
  28839.  
  28840.  623. .EXE Header Must Be Marked for OS/2 Long Filename Support
  28841.  
  28842.  Product Version(s): 6.00 6.00a
  28843.  Operating System:   OS/2
  28844.  Flags: ENDUSER | s_exehdr
  28845.  Last Modified:  1-FEB-1991    ArticleIdent: Q67878
  28846.  
  28847.  Applications using long filenames and extended file attributes are
  28848.  supported under OS/2 versions 1.20 and later running the high
  28849.  performance file system (HPFS); however, a bit in the executable file
  28850.  must be set to tell OS/2 that the executable file supports long
  28851.  filenames.
  28852.  
  28853.  The following lists two possible methods to specify that the
  28854.  application supports long filenames:
  28855.  
  28856.  1. Modify the executable file using the EXEHDR utility:
  28857.  
  28858.        EXEHDR /NEWFILES test.exe
  28859.  
  28860.  2. Link with a module definition file containing the following line
  28861.     specifying the optional attribute <NEWFILES>:
  28862.  
  28863.        NAME [appname] [apptype] NEWFILES
  28864.  
  28865.  
  28866.  624. R6002 "Floating Point Not Loaded" May Result from printf() Use
  28867.  
  28868.  Product Version(s): 3.00 4.00 5.00 5.10 6.00 6.00a | 5.10 6.00 6.00a
  28869.  Operating System:   MS-DOS                         | OS/2
  28870.  Flags: ENDUSER | s_quickc
  28871.  Last Modified:  4-DEC-1990    ArticleIdent: Q23873
  28872.  
  28873.  Question:
  28874.  
  28875.  I have a simple program that prints out some numbers. Every time I try
  28876.  to run the program, I get the error message "R6002: Floating point
  28877.  support not loaded." Why do I get this error when I don't have any
  28878.  floats in my program?
  28879.  
  28880.  Response:
  28881.  
  28882.  You most likely have a printf() statement in your program that
  28883.  contains a floating point format specifier, such as %f in the format
  28884.  string. At link time, the floating-point library modules will not be
  28885.  loaded unless floats are declared.