dev-cpp-users Mailing List for Dev-C++ (Page 618)
Open Source C & C++ IDE for Windows
Brought to you by:
claplace
You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(15) |
Oct
(115) |
Nov
(154) |
Dec
(258) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(377) |
Feb
(260) |
Mar
(249) |
Apr
(188) |
May
(152) |
Jun
(150) |
Jul
(195) |
Aug
(202) |
Sep
(200) |
Oct
(286) |
Nov
(242) |
Dec
(165) |
| 2002 |
Jan
(245) |
Feb
(241) |
Mar
(239) |
Apr
(346) |
May
(406) |
Jun
(369) |
Jul
(418) |
Aug
(357) |
Sep
(362) |
Oct
(597) |
Nov
(455) |
Dec
(344) |
| 2003 |
Jan
(446) |
Feb
(397) |
Mar
(515) |
Apr
(524) |
May
(377) |
Jun
(387) |
Jul
(532) |
Aug
(364) |
Sep
(294) |
Oct
(352) |
Nov
(295) |
Dec
(327) |
| 2004 |
Jan
(416) |
Feb
(318) |
Mar
(324) |
Apr
(249) |
May
(259) |
Jun
(218) |
Jul
(212) |
Aug
(259) |
Sep
(158) |
Oct
(162) |
Nov
(214) |
Dec
(169) |
| 2005 |
Jan
(111) |
Feb
(165) |
Mar
(199) |
Apr
(147) |
May
(131) |
Jun
(163) |
Jul
(235) |
Aug
(136) |
Sep
(84) |
Oct
(88) |
Nov
(113) |
Dec
(100) |
| 2006 |
Jan
(85) |
Feb
(119) |
Mar
(33) |
Apr
(31) |
May
(56) |
Jun
(68) |
Jul
(18) |
Aug
(62) |
Sep
(33) |
Oct
(55) |
Nov
(19) |
Dec
(40) |
| 2007 |
Jan
(22) |
Feb
(49) |
Mar
(34) |
Apr
(51) |
May
(66) |
Jun
(43) |
Jul
(116) |
Aug
(57) |
Sep
(70) |
Oct
(69) |
Nov
(97) |
Dec
(86) |
| 2008 |
Jan
(32) |
Feb
(47) |
Mar
(106) |
Apr
(67) |
May
(28) |
Jun
(39) |
Jul
(31) |
Aug
(25) |
Sep
(18) |
Oct
(25) |
Nov
(5) |
Dec
(21) |
| 2009 |
Jan
(33) |
Feb
(27) |
Mar
(27) |
Apr
(22) |
May
(22) |
Jun
(10) |
Jul
(17) |
Aug
(9) |
Sep
(21) |
Oct
(13) |
Nov
(4) |
Dec
(11) |
| 2010 |
Jan
(10) |
Feb
(8) |
Mar
(4) |
Apr
(1) |
May
|
Jun
(2) |
Jul
|
Aug
(1) |
Sep
(8) |
Oct
(26) |
Nov
(9) |
Dec
(1) |
| 2011 |
Jan
(21) |
Feb
(16) |
Mar
(4) |
Apr
(19) |
May
(26) |
Jun
(9) |
Jul
(6) |
Aug
|
Sep
(4) |
Oct
(3) |
Nov
(2) |
Dec
(1) |
| 2012 |
Jan
(4) |
Feb
(7) |
Mar
(4) |
Apr
|
May
(1) |
Jun
(10) |
Jul
(1) |
Aug
(1) |
Sep
(18) |
Oct
(3) |
Nov
(1) |
Dec
(1) |
| 2013 |
Jan
(4) |
Feb
(2) |
Mar
(15) |
Apr
(6) |
May
(1) |
Jun
(3) |
Jul
(1) |
Aug
(2) |
Sep
(4) |
Oct
|
Nov
(9) |
Dec
|
| 2014 |
Jan
(4) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(5) |
Aug
(4) |
Sep
|
Oct
(2) |
Nov
(1) |
Dec
(4) |
| 2015 |
Jan
(2) |
Feb
(3) |
Mar
(1) |
Apr
(2) |
May
(1) |
Jun
(2) |
Jul
|
Aug
(1) |
Sep
(2) |
Oct
(9) |
Nov
(35) |
Dec
(6) |
| 2016 |
Jan
(7) |
Feb
(10) |
Mar
(10) |
Apr
(9) |
May
(13) |
Jun
(9) |
Jul
(1) |
Aug
(3) |
Sep
(3) |
Oct
(1) |
Nov
(1) |
Dec
|
| 2017 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2018 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2019 |
Jan
(1) |
Feb
|
Mar
|
Apr
(2) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2020 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Hans V. <vis...@ho...> - 2002-02-26 08:57:53
|
Thank you! |
|
From: Claus P. <cl...@vi...> - 2002-02-26 07:55:13
|
Thank you! |
|
From: <jor...@wa...> - 2002-02-26 05:47:11
|
Un saludo, jor...@wa... |
|
From: Fierytycoon <fie...@ya...> - 2002-02-26 00:45:28
|
Hey, How can I manually add/edit a .def file in a dll project? As of now, it always seems to attempt to generate a new one every time I compile my project. Please reply with info, thanks. Fierytycoon --------------------------------- Do You Yahoo!? Yahoo! Sports - Coverage of the 2002 Olympic Games |
|
From: Fierytycoon <fie...@ya...> - 2002-02-26 00:45:22
|
Hey, How can I manual add/edit a .def file in a dll project? As of now, it always seems to attempt to generate a new one every time I compile my project. Please reply with info, thanks. Fierytycoon --------------------------------- Do You Yahoo!? Yahoo! Sports - Coverage of the 2002 Olympic Games |
|
From: Benjamin W. <ben...@ho...> - 2002-02-25 22:23:12
|
<html><div style='background-color:'><DIV>
<P>Thanks Gents (Ioannis & Jason). I appreciate the help on this one.</P>
<P>Have a good afternoon.</P></DIV>
<DIV></DIV>
<DIV><FONT face="Geneva, Arial, Sans-serif" size=2>Benjamin Wheeless</FONT></DIV>
<DIV></DIV>
<DIV><FONT face="Geneva, Arial, Sans-serif" size=2><STRONG>Network Systems - Delta Airlines, Inc.</STRONG></FONT></DIV>
<DIV></DIV>
<DIV><FONT face=Arial size=2><STRONG>Atlanta, GA - USA 30320</STRONG></FONT></DIV>
<DIV></DIV>
<DIV><FONT face=Arial size=2><STRONG>==============================</STRONG></FONT></DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>----Original Message Follows----
<DIV></DIV>From: "Ioannis Vranos" <NO...@YA...>
<DIV></DIV>To: "Dev-C++" <DEV...@LI...>
<DIV></DIV>Subject: RE: [Dev-C++] Time stamping an output file.
<DIV></DIV>Date: Mon, 25 Feb 2002 21:18:48 +0200
<DIV></DIV>
<DIV></DIV>I am sorry obviously i did not understand the question. I thought you
<DIV></DIV>wanted to manipulate the date/time stamp of the files, but you wanted to
<DIV></DIV>put a string to the filename. You can use the functions ctime() and
<DIV></DIV>time() of time.h in the style:
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>#include <STDIO.H>
<DIV></DIV>#include <STDLIB.H>
<DIV></DIV>#include <STRING.H>
<DIV></DIV>#include <TIME.H>
<DIV></DIV>
<DIV></DIV>int main(void)
<DIV></DIV>{
<DIV></DIV>char filename[]="some filename - ";
<DIV></DIV>time_t tp=time(NULL);
<DIV></DIV>char *s=ctime(&tp);
<DIV></DIV>char *newname=malloc(strlen(filename)+strlen(s)+1);
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>if(!newname)
<DIV></DIV>return EXIT_FAILURE;
<DIV></DIV>
<DIV></DIV>strcpy(newname, filename);
<DIV></DIV>strcat(newname, s);
<DIV></DIV>
<DIV></DIV>puts(newname);
<DIV></DIV>
<DIV></DIV>return 0;
<DIV></DIV>}
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>Keep in mind that this operation is portable, that is it works
<DIV></DIV>everywhere.
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>Ioannis
<DIV></DIV>
<DIV></DIV>* Ioannis Vranos
<DIV></DIV>* Programming pages:
<DIV></DIV>http://www.noicys.d2g.com
<DIV></DIV>* Alternative URL: http://run.to/noicys
<DIV></DIV>
<DIV></DIV>-----Original Message-----
<DIV></DIV>From: dev...@li...
<DIV></DIV>[mailto:dev...@li...] On Behalf Of Ioannis
<DIV></DIV>Vranos
<DIV></DIV>Sent: Monday, February 25, 2002 8:42 PM
<DIV></DIV>To: Dev-C++
<DIV></DIV>Subject: RE: [Dev-C++] Time stamping an output file.
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>You can do it with win32 api:
<DIV></DIV>
<DIV></DIV>Syntax
<DIV></DIV>
<DIV></DIV>#include <IO.H>
<DIV></DIV>int getftime(int handle, struct ftime *ftimep);
<DIV></DIV>int setftime(int handle, struct ftime *ftimep);
<DIV></DIV>
<DIV></DIV>[ Useless things ]
<DIV></DIV>
<DIV></DIV></div><br clear=all><hr>Send and receive Hotmail on your mobile device: <a href='http://go.msn.com/bql/hmtag2_etl_EN.asp'>Click Here</a><br></html>
|
|
From: flxlist <fl...@ya...> - 2002-02-25 20:05:35
|
Dev-C++ can compile the followingsimple testprogram but the program
doesn't function afterwards:
#include <fstream.h>
class Animal
{
public:
Animal(int weight, long
days):itsWeight(weight),itsNumberDaysAlive(days){}
~Animal(){}
int GetWeight()const { return itsWeight; }
void SetWeight(int weight) { itsWeight = weight; }
long GetDaysAlive()const { return itsNumberDaysAlive; }
void SetDaysAlive(long days) { itsNumberDaysAlive = days; }
private:
int itsWeight;
long itsNumberDaysAlive;
};
int main() // returns 1 on error
{
char fileName[80];
cout << "Please enter the file name: ";
cin >> fileName;
ofstream fout(fileName,ios::binary);
if (!fout)
{
cout << "Unable to open " << fileName << " for writing.\n";
return(1);
}
Animal Bear(50,100);
fout.write((char*) &Bear,sizeof Bear);
fout.close();
ifstream fin(fileName,ios::binary);
if (!fin)
{
cout << "Unable to open " << fileName << " for reading.\n";
return(1);
}
Animal BearTwo(1,1);
cout << "BearTwo weight: " << BearTwo.GetWeight() << endl;
cout << "BearTwo days: " << BearTwo.GetDaysAlive() << endl;
fin.read((char*) &BearTwo, sizeof BearTwo);
cout << "BearTwo weight: " << BearTwo.GetWeight() << endl;
cout << "BearTwo days: " << BearTwo.GetDaysAlive() << endl;
fin.close();
return 0;
}
If I use any other compiler like DJGPP or Borland 5.5 it does work.
Does anybody know why it doesn't work with Dev-C++?
And does anyone know how to fix the problem?
Felixz
fl...@ya...
|
|
From: Ioannis V. <no...@ya...> - 2002-02-25 19:18:53
|
I am sorry obviously i did not understand the question. I thought you
wanted to manipulate the date/time stamp of the files, but you wanted to
put a string to the filename. You can use the functions ctime() and
time() of time.h in the style:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(void)
{
char filename[]="some filename - ";
time_t tp=time(NULL);
char *s=ctime(&tp);
char *newname=malloc(strlen(filename)+strlen(s)+1);
if(!newname)
return EXIT_FAILURE;
strcpy(newname, filename);
strcat(newname, s);
puts(newname);
return 0;
}
Keep in mind that this operation is portable, that is it works
everywhere.
Ioannis
* Ioannis Vranos
* Programming pages: <http://www.noicys.d2g.com/>
http://www.noicys.d2g.com
* Alternative URL: <http://run.to/noicys> http://run.to/noicys
-----Original Message-----
From: dev...@li...
[mailto:dev...@li...] On Behalf Of Ioannis
Vranos
Sent: Monday, February 25, 2002 8:42 PM
To: Dev-C++
Subject: RE: [Dev-C++] Time stamping an output file.
You can do it with win32 api:
Syntax
#include <io.h>
int getftime(int handle, struct ftime *ftimep);
int setftime(int handle, struct ftime *ftimep);
[ Useless things ]
|
|
From: Jason H. <jas...@bt...> - 2002-02-25 18:55:42
|
If you want to obtain the date in a way that is standard to C or C++ =
then you can use the functions supplied in the <time.h> header. I leave =
it to you to look at what it supplies in whatever C reference material =
you have (I'm too tired).
Jason.
----- Original Message -----=20
From: Benjamin Wheeless=20
To: dev...@so...=20
Sent: Monday, February 25, 2002 5:25 PM
Subject: [Dev-C++] Time stamping an output file.
Good afternoon,
Quick question that is probably much easier than I'm thinking it is...
Does anyone out there know how to easily put a date stamp on an output =
file using C rather than using the environments shell? I know how to do =
it using Korn, but I'm working on WinNT and so I need the source code to =
do it rather than cmd.exe(unless cmd.exe can do it easier via a batch =
file or something)...
For example:
-output file name =3D hsloan.txt
-would like output file name =3D hsloanYYYYMMDD.txt
(where YYYYMMDD =3D (year)(month)(date) of course)
Keep in mind that I'm using: fopen( "C:\\temp\\hsloan.txt", "w" =
) ;
Any thoughts/suggestions?
P.S. -- Ioannis, can I cash in some of those EuroCents now?
Benjamin Wheeless
Network Systems - Delta Airlines, Inc.
Atlanta, GA - USA 30320
=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
-------------------------------------------------------------------------=
-----
MSN Photos is the easiest way to share and print your photos: Click =
Here
_______________________________________________ Dev-cpp-users mailing =
list Dev...@li... =
https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
|
|
From: Ioannis V. <no...@ya...> - 2002-02-25 18:42:15
|
You can do it with win32 api:
Syntax
#include <io.h>
int getftime(int handle, struct ftime *ftimep);
int setftime(int handle, struct ftime *ftimep);
The file must be open for writing; an EACCES error will occur if the
file is open for read-only access.
struct ftime {
unsigned ft_tsec: 5; /* two seconds */
unsigned ft_min: 6; /* minutes */
unsigned ft_hour: 5; /* hours */
unsigned ft_day: 5; /* days */
unsigned ft_month: 4; /* months */
unsigned ft_year: 7; /* year - 1980*/
};
getftime, setftime
See also Examples Portability
Header File
io.h
Category
Input/output Routines
Syntax
#include <io.h>
int getftime(int handle, struct ftime *ftimep);
int setftime(int handle, struct ftime *ftimep);
Description
Gets and sets the file date and time.
getftime retrieves the file time and date for the disk file associated
with the open handle. The ftime structure pointed to by ftimep is filled
in with the file's time and date.
setftime sets the file date and time of the disk file associated with
the open handle to the date and time in the ftime structure pointed to
by ftimep. The file must not be written to after the setftime call or
the changed information will be lost. The file must be open for writing;
an EACCES error will occur if the file is open for read-only access.
They require the file to be open for writing; an EACCES error will occur
if the file is open for read-only access.
The ftime structure is defined as follows:
struct ftime {
unsigned ft_tsec: 5; /* two seconds */
unsigned ft_min: 6; /* minutes */
unsigned ft_hour: 5; /* hours */
unsigned ft_day: 5; /* days */
unsigned ft_month: 4; /* months */
unsigned ft_year: 7; /* year - 1980*/
};
Return Value
getftime and setftime return 0 on success.
In the event of an error return -1 is returned and the global variable
errno is set to one of the following values:
EACCES Permission denied
EBADF Bad file number
EINVFNC Invalid function number
Example:
FILE *stream;
std::ftime ft;
if ((stream = fopen("TEST.$$$",
"wt")) == NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
getftime(fileno(stream), &ft);
printf("File time: %u:%u:%u\n",
ft.ft_hour, ft.ft_min,
ft.ft_tsec * 2);
Ioannis
* Ioannis Vranos
* Programming pages: <http://www.noicys.d2g.com/>
http://www.noicys.d2g.com
* Alternative URL: <http://run.to/noicys> http://run.to/noicys
-----Original Message-----
From: dev...@li...
[mailto:dev...@li...] On Behalf Of Benjamin
Wheeless
Sent: Monday, February 25, 2002 7:26 PM
To: dev...@so...
Subject: [Dev-C++] Time stamping an output file.
Good afternoon,
Quick question that is probably much easier than I'm thinking it is...
Does anyone out there know how to easily put a date stamp on an output
file using C rather than using the environments shell? I know how to do
it using Korn, but I'm working on WinNT and so I need the source code to
do it rather than cmd.exe(unless cmd.exe can do it easier via a batch
file or something)...
For example:
-output file name = hsloan.txt
-would like output file name = hsloanYYYYMMDD.txt
(where YYYYMMDD = (year)(month)(date) of course)
Keep in mind that I'm using: fopen( "C:\\temp\\hsloan.txt", "w" )
;
Any thoughts/suggestions?
P.S. -- Ioannis, can I cash in some of those EuroCents now?
Benjamin Wheeless
Network Systems - Delta Airlines, Inc.
Atlanta, GA - USA 30320
==============================
_____
MSN Photos is the easiest way to share and print your photos: Click
<http://go.msn.com/bql/hmtag3_etl_EN.asp> Here
_______________________________________________ Dev-cpp-users mailing
list Dev...@li...
https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
|
|
From: Benjamin W. <ben...@ho...> - 2002-02-25 17:25:58
|
<html><div style='background-color:'><DIV></DIV> <DIV></DIV> <P>Good afternoon,</P> <P>Quick question that is probably much easier than I'm thinking it is...</P> <P>Does anyone out there know how to easily put a date stamp on an output file using C rather than using the environments shell? I know how to do it using Korn, but I'm working on WinNT and so I need the source code to do it rather than cmd.exe(unless cmd.exe can do it easier via a batch file or something)...<BR><BR>For example:<BR> -output file name = hsloan.txt<BR> -would like output file name = hsloanYYYYMMDD.txt<BR> (where YYYYMMDD = (year)(month)(date) of course)<BR><BR>Keep in mind that I'm using: fopen( "C:\\temp\\hsloan.txt", "w" ) ;</P> <P>Any thoughts/suggestions?</P> <P>P.S. -- Ioannis, can I cash in some of those EuroCents now?</P> <DIV></DIV> <DIV><FONT face="Geneva, Arial, Sans-serif" size=2>Benjamin Wheeless</FONT></DIV> <DIV></DIV> <DIV><FONT face="Geneva, Arial, Sans-serif" size=2><STRONG>Network Systems - Delta Airlines, Inc.</STRONG></FONT></DIV> <DIV></DIV> <DIV><FONT face=Arial size=2><STRONG>Atlanta, GA - USA 30320</STRONG></FONT></DIV> <DIV></DIV> <DIV><FONT face=Arial size=2><STRONG>==============================</STRONG></FONT></DIV> <DIV></DIV> <DIV></DIV></div><br clear=all><hr>MSN Photos is the easiest way to share and print your photos: <a href='http://go.msn.com/bql/hmtag3_etl_EN.asp'>Click Here</a><br></html> |
|
From: jansb000 <jan...@wx...> - 2002-02-25 16:02:08
|
The usage of wildcards in unix is normally handled by the shell. Hence, calling a program like this: "prg *.txt" is translated to "prg 1.txt 2.txt ...". In DOS there is no such default handling of wildcards. Compiler builders must make there own solution. DJGPP and MINGW32 (DevC++) simulate the unix method, probably to maintain platform independency. For BCC you can get the arguments as-is, this it what we see here, or you can link the file "wildargs.obj" in your project. That should give you the same results as with DJGPP or MINGW32. (I found this in my old Turbo C++ 3.0 users guide). ----- Original Message ----- > > command output > echo_g *.c bar.c foo.c > echo_b *.c *.c |
|
From: Zodiaq <zo...@ac...> - 2002-02-25 15:40:51
|
Hello Dev-C++ Users, well, first: I'm new here so I would like to say just hey! Second: I have this problem - I can't create working TabControl app under DevC++ 4.01... does anybody have example of how to make some tabs? I tried to compile example from M$ Platform SDK but without success :-\\ -- regards Zodiaq... from Poland :-]]] |
|
From: Benjamin W. <ben...@ho...> - 2002-02-25 15:12:23
|
<html><div style='background-color:'><DIV> <P>I'll try not to spend it all in one place. Thanks! :)</P></DIV> <DIV></DIV> <DIV><FONT face="Geneva, Arial, Sans-serif" size=2>Benjamin Wheeless</FONT></DIV> <DIV></DIV> <DIV><FONT face="Geneva, Arial, Sans-serif" size=2><STRONG>Network Systems - Delta Airlines, Inc.</STRONG></FONT></DIV> <DIV></DIV> <DIV><FONT face=Arial size=2><STRONG>Atlanta, GA - USA 30320</STRONG></FONT></DIV> <DIV></DIV> <DIV><FONT face=Arial size=2><STRONG>==============================</STRONG></FONT></DIV> <DIV> </DIV> <DIV></DIV> <DIV></DIV> <DIV></DIV> <DIV></DIV> <DIV></DIV>----Original Message Follows---- <DIV></DIV>From: "Ioannis Vranos" <NO...@YA...> <DIV></DIV>To: "Dev-C++" <DEV...@LI...> <DIV></DIV>Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell <DIV></DIV>Date: Mon, 25 Feb 2002 16:45:19 +0200 <DIV></DIV> <DIV></DIV>-----Original Message----- <DIV></DIV>From: dev...@li... <DIV></DIV>[mailto:dev...@li...] On Behalf Of Benjamin <DIV></DIV>Wheeless <DIV></DIV>Sent: Monday, February 25, 2002 3:28 PM <DIV></DIV>To: dev...@so... <DIV></DIV>Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell <DIV></DIV> <DIV></DIV> <DIV></DIV> <DIV></DIV>Anyway, just my two cents worth. Have a great day! <DIV></DIV> <DIV></DIV> <DIV></DIV>Ioannis gives to Benjamin 10 Eurocents. Keep the change. :) <DIV></DIV> <DIV></DIV> <DIV></DIV> <DIV></DIV> <DIV></DIV>Ioannis <DIV></DIV> <DIV></DIV>* Ioannis Vranos <DIV></DIV>* Programming pages: <DIV></DIV>http://www.noicys.d2g.com <DIV></DIV>* Alternative URL: http://run.to/noicys <DIV></DIV> <DIV></DIV></div><br clear=all><hr>Get your FREE download of MSN Explorer at <a href='http://go.msn.com/bql/hmtag_etl_EN.asp'>http://explorer.msn.com</a>.<br></html> |
|
From: Ioannis V. <no...@ya...> - 2002-02-25 14:45:34
|
-----Original Message----- From: dev...@li... [mailto:dev...@li...] On Behalf Of Benjamin Wheeless Sent: Monday, February 25, 2002 3:28 PM To: dev...@so... Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell Anyway, just my two cents worth. Have a great day! Ioannis gives to Benjamin 10 Eurocents. Keep the change. :) Ioannis * Ioannis Vranos * Programming pages: <http://www.noicys.d2g.com/> http://www.noicys.d2g.com * Alternative URL: <http://run.to/noicys> http://run.to/noicys |
|
From: Benjamin W. <ben...@ho...> - 2002-02-25 13:28:02
|
<html><div style='background-color:'><DIV>
<P>Good morning,</P>
<P>I guess I am just restating what the other two gentlemen already have...but to me, it sounds like more of a discrepancy within the two compilers rather than something wrong with the Win98 Shell.</P>
<P>Exactly what that discrepancy is, I do not know. As for which is performing correctly...I'm not sure that is a valid statement or question...it really depends on what the programmer's intention is...and I would say that they are both performing correctly, perhaps just not as expected since they give different results.</P>
<P>Anyway, just my two cents worth. Have a great day!</P></DIV>
<DIV></DIV>
<DIV><FONT face="Geneva, Arial, Sans-serif" size=2>Benjamin Wheeless</FONT></DIV>
<DIV></DIV>
<DIV><FONT face="Geneva, Arial, Sans-serif" size=2><STRONG>Network Systems - Delta Airlines, Inc.</STRONG></FONT></DIV>
<DIV></DIV>
<DIV><FONT face=Arial size=2><STRONG>Atlanta, GA - USA 30320</STRONG></FONT></DIV>
<DIV></DIV>
<DIV><FONT face=Arial size=2><STRONG>==============================</STRONG></FONT></DIV>
<DIV> </DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>----Original Message Follows----
<DIV></DIV>From: gi...@li...
<DIV></DIV>To: dev...@so...
<DIV></DIV>Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell
<DIV></DIV>Date: Sun, 24 Feb 2002 23:37:51 +0100
<DIV></DIV>
<DIV></DIV>Sorry for my previous post, it was not very clear.
<DIV></DIV>
<DIV></DIV>Let me try again.
<DIV></DIV>
<DIV></DIV>The test program is, this time, a little different:
<DIV></DIV>
<DIV></DIV>/* echo.c */
<DIV></DIV>#include <STDIO.H>
<DIV></DIV>int main(int argc, char *argv[])
<DIV></DIV>{
<DIV></DIV>while (--argc > 0)
<DIV></DIV>printf("%s%s", *++argv, (argc > 1) ? " ": "");
<DIV></DIV>printf("\n");
<DIV></DIV>return 0;
<DIV></DIV>}
<DIV></DIV>
<DIV></DIV>IMHO the above is more or less equivalent to the program I posted before
<DIV></DIV>but I changed in the hope that Ioannis won't yell at me this time :-)
<DIV></DIV>
<DIV></DIV>Anyway the program is not the point, it is just a mean to show that:
<DIV></DIV>when I use a program compiled by gcc, it seems that the shell expands
<DIV></DIV>wildcards before invoking the program (as it should always be), instead
<DIV></DIV>when I compile the same program using BC++, the shell does not expand the
<DIV></DIV>wildcards.
<DIV></DIV>
<DIV></DIV>To prove it, what I did was:
<DIV></DIV>1. create a directory named c:\temp
<DIV></DIV>2. used the program "touch" (a Borland tool) to create: c:\temp\foo.c and
<DIV></DIV>c:\temp\bar.c
<DIV></DIV>3. switched to the directory c:\temp
<DIV></DIV>4. issued the command: echo_g *.c
<DIV></DIV>
<DIV></DIV>The ouput of the command was:
<DIV></DIV>
<DIV></DIV>bar.c foo.c
<DIV></DIV>
<DIV></DIV>This means that the shell expanded "*.c" into "bar.c foo.c", the two
<DIV></DIV>arguments were then echoed by the program "echo_g" (where the "_g" means
<DIV></DIV>compiled using gcc).
<DIV></DIV>
<DIV></DIV>Instead if I use the version of echo compiled by BC++ (named "echo_b.exe"),
<DIV></DIV>that is, when step #4 becomes:
<DIV></DIV>
<DIV></DIV>4. issued the command: echo_b *.c
<DIV></DIV>
<DIV></DIV>The output is:
<DIV></DIV>
<DIV></DIV>*.c
<DIV></DIV>
<DIV></DIV>This means that the shell did not expand "*.c". Or, if you prefer, I have
<DIV></DIV>the same ANSI C89 program give two different outputs, according to which
<DIV></DIV>compiler was used to build the executable. I have no explanation for this,
<DIV></DIV>other than there is some bug in the shell.
<DIV></DIV>
<DIV></DIV>My questions are
<DIV></DIV>1. Why is the Windows shell (or command.com, if you prefer) acting
<DIV></DIV>differently?
<DIV></DIV>2. Is this happening on my Win98SE or is it happening on other versions of
<DIV></DIV>Windows too?
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>At 18:45 24/02/02 +0200, Ioannis Vranos wrote:
<DIV></DIV>> > -----Original Message-----
<DIV></DIV>> > From: dev...@li...
<DIV></DIV>> > [mailto:dev...@li...] On Behalf
<DIV></DIV>> > Of gi...@li...
<DIV></DIV>> > Sent: Sunday, February 24, 2002 5:03 PM
<DIV></DIV>> > To: dev...@so...
<DIV></DIV>> > Subject: [Dev-C++] BC++, gcc and Win98SE shell
<DIV></DIV>> >
<DIV></DIV>> >
<DIV></DIV>> > Hello list,
<DIV></DIV>> >
<DIV></DIV>> > here is one, funny, thing of which I have no explanation:
<DIV></DIV>> >
<DIV></DIV>> > consider the following program:
<DIV></DIV>> >
<DIV></DIV>> > /* echo.c */
<DIV></DIV>> > #include <STDIO.H>
<DIV></DIV>> >
<DIV></DIV>> > int
<DIV></DIV>> > main(int argc, char **argv)
<DIV></DIV>> > {
<DIV></DIV>> > while (--argc)
<DIV></DIV>>
<DIV></DIV>> This decreases the number reported, which has no effect.
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>> > printf("%s ", *++argv);
<DIV></DIV>>
<DIV></DIV>>Here you printf *after* you increment, that is you lose the first
<DIV></DIV>>string.
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>Now something delicate. argc is *not* guaranteed to be one if you do
<DIV></DIV>>not
<DIV></DIV>>pass any argument. It is guaranteed that if you pass an argument
<DIV></DIV>>then it
<DIV></DIV>>will be non zero and argv[0] will be the name of the program itself.
<DIV></DIV>>In
<DIV></DIV>>few words, if you do not pass any name it is not guaranteed that
<DIV></DIV>>argv[0]
<DIV></DIV>>contains the name of the program. As the C++ standard says:
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>"An implementation shall not predefine the main function. This
<DIV></DIV>>function
<DIV></DIV>>shall not be overloaded. It shall
<DIV></DIV>>have a return type of type int, but otherwise its type is
<DIV></DIV>>implementationdefined.
<DIV></DIV>>All implementations
<DIV></DIV>>shall allow both of the following definitions of main:
<DIV></DIV>>int main() { /* ... */ }
<DIV></DIV>>and
<DIV></DIV>>int main(int argc, char* argv[]) { /* ... */ }
<DIV></DIV>>In the latter form argc shall be the number of arguments passed to
<DIV></DIV>>the
<DIV></DIV>>program from the environment in
<DIV></DIV>>which the program is run. If argc is nonzero these arguments shall
<DIV></DIV>>be
<DIV></DIV>>supplied in argv[0] through
<DIV></DIV>>argv[argc1]
<DIV></DIV>>as pointers to the initial characters of nullterminated
<DIV></DIV>>multibyte strings (NTMBSs)
<DIV></DIV>>(17.3.2.1.3.2) and argv[0] shall be the pointer to the initial
<DIV></DIV>>character
<DIV></DIV>>of a NTMBS that represents the
<DIV></DIV>>name used to invoke the program or "". The value of argc shall be
<DIV></DIV>>nonnegative. The value of
<DIV></DIV>>argv[argc] shall be 0. [Note: it is recommended that any further
<DIV></DIV>>(optional) parameters be added after
<DIV></DIV>>argv. ]".
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>This is exactly the same for ANSI C89 and C99 too.
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>> >
<DIV></DIV>> > return 0;
<DIV></DIV>> > }
<DIV></DIV>> >
<DIV></DIV>> > I compiled it using:
<DIV></DIV>> > GNU gcc 2.95 shipped with Dev-C++ (gcc -o echo_g.exe echo.c)
<DIV></DIV>> > BC++ 5.5 of thge "Borland free command line tools" (bcc32
<DIV></DIV>>-eecho_b.exe
<DIV></DIV>> > echo.c).
<DIV></DIV>> >
<DIV></DIV>> > Then I've "touched" the files "foo.c" and "bar.c" and tried
<DIV></DIV>> > the following:
<DIV></DIV>> >
<DIV></DIV>> > command output
<DIV></DIV>> > echo_g *.c bar.c foo.c
<DIV></DIV>> > echo_b *.c *.c
<DIV></DIV>> >
<DIV></DIV>> > All of this on Win98SE.
<DIV></DIV>> > Is there somebody that can tell what is going on?
<DIV></DIV>> > Is this bug(?) common to the shell of other Windows systems too?
<DIV></DIV>>
<DIV></DIV>>I do not understand what you did.
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>
<DIV></DIV>>Ioannis
<DIV></DIV>>
<DIV></DIV>>* Ioannis Vranos
<DIV></DIV>>* Programming pages: http://www.noicys.d2g.com
<DIV></DIV>>* Alternative URL: http://run.to/noicys
<DIV></DIV>>
<DIV></DIV>
<DIV></DIV>--
<DIV></DIV>gisan
<DIV></DIV>gi...@li...
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>_______________________________________________
<DIV></DIV>Dev-cpp-users mailing list
<DIV></DIV>Dev...@li...
<DIV></DIV>https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
<DIV></DIV></div><br clear=all><hr>Send and receive Hotmail on your mobile device: <a href='http://go.msn.com/bql/hmtag2_etl_EN.asp'>Click Here</a><br></html>
|
|
From: Jason H. <jas...@bt...> - 2002-02-25 01:47:07
|
One possible reason for this behaviour may be due to differences between the
Windows and Unix (i.e. Linux) environments. I'm uncertain of the actual
behaviours but your program implies that the shell of Windows doesn't have
direct support for wildcards, and that wildcard operation has to be built
into the programs themselves. In Unix on the other hand it may be that
wildcards are automatically expanded to their equivalents in the file
system. Because GCC is a port of a Unix compiler then the operation may have
been passed through to the windows version for compatibility, whereas BC++
is developed for windows directly.
From the C++ specification (from Ioannis message) there is no mention of any
default handling of wildcards, and it would be dependent upon the OS itself.
Another explanation may be a compiler feature that is turned on in GCC,
where it may handle the chore of dealing with wildcards for you. If true
there may be a way of disabling the feature. BC++ may not have this feature
or it may be turned off by default. I find this explanation unlikely though.
Try checking the documentations for both compilers.
Jason.
----- Original Message -----
From: <gi...@li...>
To: <dev...@so...>
Sent: Sunday, February 24, 2002 10:37 PM
Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell
> Sorry for my previous post, it was not very clear.
>
> Let me try again.
>
> The test program is, this time, a little different:
>
> /* echo.c */
> #include <stdio.h>
> int main(int argc, char *argv[])
> {
> while (--argc > 0)
> printf("%s%s", *++argv, (argc > 1) ? " ": "");
> printf("\n");
> return 0;
> }
>
> IMHO the above is more or less equivalent to the program I posted before
> but I changed in the hope that Ioannis won't yell at me this time :-)
>
> Anyway the program is not the point, it is just a mean to show that:
> when I use a program compiled by gcc, it seems that the shell expands
> wildcards before invoking the program (as it should always be), instead
> when I compile the same program using BC++, the shell does not expand the
> wildcards.
>
> To prove it, what I did was:
> 1. create a directory named c:\temp
> 2. used the program "touch" (a Borland tool) to create: c:\temp\foo.c and
> c:\temp\bar.c
> 3. switched to the directory c:\temp
> 4. issued the command: echo_g *.c
>
> The ouput of the command was:
>
> bar.c foo.c
>
> This means that the shell expanded "*.c" into "bar.c foo.c", the two
> arguments were then echoed by the program "echo_g" (where the "_g" means
> compiled using gcc).
>
> Instead if I use the version of echo compiled by BC++ (named
"echo_b.exe"),
> that is, when step #4 becomes:
>
> 4. issued the command: echo_b *.c
>
> The output is:
>
> *.c
>
> This means that the shell did not expand "*.c". Or, if you prefer, I have
> the same ANSI C89 program give two different outputs, according to which
> compiler was used to build the executable. I have no explanation for this,
> other than there is some bug in the shell.
>
> My questions are
> 1. Why is the Windows shell (or command.com, if you prefer) acting
> differently?
> 2. Is this happening on my Win98SE or is it happening on other versions of
> Windows too?
>
>
> At 18:45 24/02/02 +0200, Ioannis Vranos wrote:
> > > -----Original Message-----
> > > From: dev...@li...
> > > [mailto:dev...@li...] On Behalf
> > > Of gi...@li...
> > > Sent: Sunday, February 24, 2002 5:03 PM
> > > To: dev...@so...
> > > Subject: [Dev-C++] BC++, gcc and Win98SE shell
> > >
> > >
> > > Hello list,
> > >
> > > here is one, funny, thing of which I have no explanation:
> > >
> > > consider the following program:
> > >
> > > /* echo.c */
> > > #include <stdio.h>
> > >
> > > int
> > > main(int argc, char **argv)
> > > {
> > > while (--argc)
> >
> > This decreases the number reported, which has no effect.
> >
> >
> > > printf("%s ", *++argv);
> >
> >Here you printf *after* you increment, that is you lose the first
> >string.
> >
> >
> >Now something delicate. argc is *not* guaranteed to be one if you do not
> >pass any argument. It is guaranteed that if you pass an argument then it
> >will be non zero and argv[0] will be the name of the program itself. In
> >few words, if you do not pass any name it is not guaranteed that argv[0]
> >contains the name of the program. As the C++ standard says:
> >
> >
> >"An implementation shall not predefine the main function. This function
> >shall not be overloaded. It shall
> >have a return type of type int, but otherwise its type is
> >implementationdefined.
> >All implementations
> >shall allow both of the following definitions of main:
> >int main() { /* ... */ }
> >and
> >int main(int argc, char* argv[]) { /* ... */ }
> >In the latter form argc shall be the number of arguments passed to the
> >program from the environment in
> >which the program is run. If argc is nonzero these arguments shall be
> >supplied in argv[0] through
> >argv[argc1]
> >as pointers to the initial characters of nullterminated
> >multibyte strings (NTMBSs)
> >(17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character
> >of a NTMBS that represents the
> >name used to invoke the program or "". The value of argc shall be
> >nonnegative. The value of
> >argv[argc] shall be 0. [Note: it is recommended that any further
> >(optional) parameters be added after
> >argv. ]".
> >
> >
> >
> >This is exactly the same for ANSI C89 and C99 too.
> >
> >
> >
> > >
> > > return 0;
> > > }
> > >
> > > I compiled it using:
> > > GNU gcc 2.95 shipped with Dev-C++ (gcc -o echo_g.exe echo.c)
> > > BC++ 5.5 of thge "Borland free command line tools" (bcc32 -eecho_b.exe
> > > echo.c).
> > >
> > > Then I've "touched" the files "foo.c" and "bar.c" and tried
> > > the following:
> > >
> > > command output
> > > echo_g *.c bar.c foo.c
> > > echo_b *.c *.c
> > >
> > > All of this on Win98SE.
> > > Is there somebody that can tell what is going on?
> > > Is this bug(?) common to the shell of other Windows systems too?
> >
> >I do not understand what you did.
> >
> >
> >
> >Ioannis
> >
> >* Ioannis Vranos
> >* Programming pages: http://www.noicys.d2g.com
> >* Alternative URL: http://run.to/noicys
> >
>
> --
> gisan
> gi...@li...
>
>
> _______________________________________________
> Dev-cpp-users mailing list
> Dev...@li...
> https://lists.sourceforge.net/lists/listinfo/dev-cpp-users
|
|
From: Ioannis V. <no...@ya...> - 2002-02-25 00:48:54
|
> -----Original Message-----
> From: dev...@li...
> [mailto:dev...@li...] On Behalf
> Of gi...@li...
> Sent: Monday, February 25, 2002 12:38 AM
> To: dev...@so...
> Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell
>
>
> Sorry for my previous post, it was not very clear.
>
> Let me try again.
>
> The test program is, this time, a little different:
>
> /* echo.c */
> #include <stdio.h>
> int main(int argc, char *argv[])
> {
> while (--argc > 0)
> printf("%s%s", *++argv, (argc > 1) ? " ": "");
> printf("\n");
> return 0;
> }
>
> IMHO the above is more or less equivalent to the program I
> posted before
> but I changed in the hope that Ioannis won't yell at me this time :-)
>
> Anyway the program is not the point, it is just a mean to
> show that: when I use a program compiled by gcc, it seems
> that the shell expands
> wildcards before invoking the program (as it should always
> be), instead
> when I compile the same program using BC++, the shell does
> not expand the
> wildcards.
>
> To prove it, what I did was:
> 1. create a directory named c:\temp
> 2. used the program "touch" (a Borland tool) to create:
> c:\temp\foo.c and
> c:\temp\bar.c
> 3. switched to the directory c:\temp
> 4. issued the command: echo_g *.c
>
> The ouput of the command was:
>
> bar.c foo.c
>
> This means that the shell expanded "*.c" into "bar.c foo.c", the two
> arguments were then echoed by the program "echo_g" (where the
> "_g" means
> compiled using gcc).
>
> Instead if I use the version of echo compiled by BC++ (named
> "echo_b.exe"),
> that is, when step #4 becomes:
>
> 4. issued the command: echo_b *.c
>
> The output is:
>
> *.c
>
> This means that the shell did not expand "*.c". Or, if you
> prefer, I have
> the same ANSI C89 program give two different outputs,
> according to which
> compiler was used to build the executable. I have no
> explanation for this,
> other than there is some bug in the shell.
This is compiler bug. **argv represents the passed arguments as a string
and i think that the behavior of BCC is the correct (expected) here.
The standard requires the exact arguments to be represented as C-strings
in *argv[] and then if the programmer wishes he can execute system
commands like system("dir *.c");
The C & C++ standards write:
"int main(int argc, char* argv[]) { /* ... */ }
In the latter form argc shall be the number of arguments passed to the
program from the environment in
which the program is run."
>
> My questions are
> 1. Why is the Windows shell (or command.com, if you prefer) acting
> differently?
I do not think it is the environment. I rather think is the use of the
environment from the produced exe (produced by the compiler).
> 2. Is this happening on my Win98SE or is it happening on
> other versions of
> Windows too?
It is happening in my win2k too and i use the cmd.exe .
Ioannis
* Ioannis Vranos
* Programming pages: http://www.noicys.d2g.com
* Alternative URL: http://run.to/noicys
|
|
From: <gi...@li...> - 2002-02-24 22:40:22
|
Sorry for my previous post, it was not very clear.
Let me try again.
The test program is, this time, a little different:
/* echo.c */
#include <stdio.h>
int main(int argc, char *argv[])
{
while (--argc > 0)
printf("%s%s", *++argv, (argc > 1) ? " ": "");
printf("\n");
return 0;
}
IMHO the above is more or less equivalent to the program I posted before
but I changed in the hope that Ioannis won't yell at me this time :-)
Anyway the program is not the point, it is just a mean to show that:
when I use a program compiled by gcc, it seems that the shell expands
wildcards before invoking the program (as it should always be), instead
when I compile the same program using BC++, the shell does not expand the
wildcards.
To prove it, what I did was:
1. create a directory named c:\temp
2. used the program "touch" (a Borland tool) to create: c:\temp\foo.c and
c:\temp\bar.c
3. switched to the directory c:\temp
4. issued the command: echo_g *.c
The ouput of the command was:
bar.c foo.c
This means that the shell expanded "*.c" into "bar.c foo.c", the two
arguments were then echoed by the program "echo_g" (where the "_g" means
compiled using gcc).
Instead if I use the version of echo compiled by BC++ (named "echo_b.exe"),
that is, when step #4 becomes:
4. issued the command: echo_b *.c
The output is:
*.c
This means that the shell did not expand "*.c". Or, if you prefer, I have
the same ANSI C89 program give two different outputs, according to which
compiler was used to build the executable. I have no explanation for this,
other than there is some bug in the shell.
My questions are
1. Why is the Windows shell (or command.com, if you prefer) acting
differently?
2. Is this happening on my Win98SE or is it happening on other versions of
Windows too?
At 18:45 24/02/02 +0200, Ioannis Vranos wrote:
> > -----Original Message-----
> > From: dev...@li...
> > [mailto:dev...@li...] On Behalf
> > Of gi...@li...
> > Sent: Sunday, February 24, 2002 5:03 PM
> > To: dev...@so...
> > Subject: [Dev-C++] BC++, gcc and Win98SE shell
> >
> >
> > Hello list,
> >
> > here is one, funny, thing of which I have no explanation:
> >
> > consider the following program:
> >
> > /* echo.c */
> > #include <stdio.h>
> >
> > int
> > main(int argc, char **argv)
> > {
> > while (--argc)
>
> This decreases the number reported, which has no effect.
>
>
> > printf("%s ", *++argv);
>
>Here you printf *after* you increment, that is you lose the first
>string.
>
>
>Now something delicate. argc is *not* guaranteed to be one if you do not
>pass any argument. It is guaranteed that if you pass an argument then it
>will be non zero and argv[0] will be the name of the program itself. In
>few words, if you do not pass any name it is not guaranteed that argv[0]
>contains the name of the program. As the C++ standard says:
>
>
>"An implementation shall not predefine the main function. This function
>shall not be overloaded. It shall
>have a return type of type int, but otherwise its type is
>implementationdefined.
>All implementations
>shall allow both of the following definitions of main:
>int main() { /* ... */ }
>and
>int main(int argc, char* argv[]) { /* ... */ }
>In the latter form argc shall be the number of arguments passed to the
>program from the environment in
>which the program is run. If argc is nonzero these arguments shall be
>supplied in argv[0] through
>argv[argc1]
>as pointers to the initial characters of nullterminated
>multibyte strings (NTMBSs)
>(17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character
>of a NTMBS that represents the
>name used to invoke the program or "". The value of argc shall be
>nonnegative. The value of
>argv[argc] shall be 0. [Note: it is recommended that any further
>(optional) parameters be added after
>argv. ]".
>
>
>
>This is exactly the same for ANSI C89 and C99 too.
>
>
>
> >
> > return 0;
> > }
> >
> > I compiled it using:
> > GNU gcc 2.95 shipped with Dev-C++ (gcc -o echo_g.exe echo.c)
> > BC++ 5.5 of thge "Borland free command line tools" (bcc32 -eecho_b.exe
> > echo.c).
> >
> > Then I've "touched" the files "foo.c" and "bar.c" and tried
> > the following:
> >
> > command output
> > echo_g *.c bar.c foo.c
> > echo_b *.c *.c
> >
> > All of this on Win98SE.
> > Is there somebody that can tell what is going on?
> > Is this bug(?) common to the shell of other Windows systems too?
>
>I do not understand what you did.
>
>
>
>Ioannis
>
>* Ioannis Vranos
>* Programming pages: http://www.noicys.d2g.com
>* Alternative URL: http://run.to/noicys
>
--
gisan
gi...@li...
|
|
From: Ioannis V. <no...@ya...> - 2002-02-24 16:49:02
|
> -----Original Message-----
> From: Ioannis Vranos [mailto:no...@ya...]
> Sent: Sunday, February 24, 2002 6:45 PM
> To: Dev-C++ (dev...@li...)
> Subject: RE: [Dev-C++] BC++, gcc and Win98SE shell
>
>
> Now something delicate. argc is *not* guaranteed to be one if
> you do not pass any argument. It is guaranteed that if you
> pass an argument then it will be non zero and argv[0] will be
> the name of the program itself. In few words, if you do not
> pass any name it is not guaranteed that argv[0] contains the
> name of the program. As the C++ standard says:
That is wrong. The correct is: If argc>0 then argv[0] is the name of the
program, e.t.c.. In few words before you use argv you must always check
if argc>0.
> "An implementation shall not predefine the main function.
> This function shall not be overloaded. It shall have a return
> type of type int, but otherwise its type is
> implementationdefined. All implementations shall allow both
> of the following definitions of main: int main() { /* ... */
> } and int main(int argc, char* argv[]) { /* ... */ } In the
> latter form argc shall be the number of arguments passed to
> the program from the environment in which the program is run.
> If argc is nonzero these arguments shall be supplied in
> argv[0] through argv[argc1] as pointers to the initial
> characters of nullterminated multibyte strings (NTMBSs)
> (17.3.2.1.3.2) and argv[0] shall be the pointer to the
> initial character of a NTMBS that represents the name used to
> invoke the program or "". The value of argc shall be
> nonnegative. The value of argv[argc] shall be 0. [Note: it is
> recommended that any further (optional) parameters be added
> after argv. ]".
>
>
>
> This is exactly the same for ANSI C89 and C99 too.
With the exception that in C it is int main(void) instead of int main().
Also C89 did not require any return value for main().
Ioannis
* Ioannis Vranos
* Programming pages: http://www.noicys.d2g.com
* Alternative URL: http://run.to/noicys
|
|
From: Ioannis V. <no...@ya...> - 2002-02-24 16:45:29
|
> -----Original Message-----
> From: dev...@li...
> [mailto:dev...@li...] On Behalf
> Of gi...@li...
> Sent: Sunday, February 24, 2002 5:03 PM
> To: dev...@so...
> Subject: [Dev-C++] BC++, gcc and Win98SE shell
>
>
> Hello list,
>
> here is one, funny, thing of which I have no explanation:
>
> consider the following program:
>
> /* echo.c */
> #include <stdio.h>
>
> int
> main(int argc, char **argv)
> {
> while (--argc)
This decreases the number reported, which has no effect.
> printf("%s ", *++argv);
Here you printf *after* you increment, that is you lose the first
string.
Now something delicate. argc is *not* guaranteed to be one if you do not
pass any argument. It is guaranteed that if you pass an argument then it
will be non zero and argv[0] will be the name of the program itself. In
few words, if you do not pass any name it is not guaranteed that argv[0]
contains the name of the program. As the C++ standard says:
"An implementation shall not predefine the main function. This function
shall not be overloaded. It shall
have a return type of type int, but otherwise its type is
implementationdefined.
All implementations
shall allow both of the following definitions of main:
int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }
In the latter form argc shall be the number of arguments passed to the
program from the environment in
which the program is run. If argc is nonzero these arguments shall be
supplied in argv[0] through
argv[argc1]
as pointers to the initial characters of nullterminated
multibyte strings (NTMBSs)
(17.3.2.1.3.2) and argv[0] shall be the pointer to the initial character
of a NTMBS that represents the
name used to invoke the program or "". The value of argc shall be
nonnegative. The value of
argv[argc] shall be 0. [Note: it is recommended that any further
(optional) parameters be added after
argv. ]".
This is exactly the same for ANSI C89 and C99 too.
>
> return 0;
> }
>
> I compiled it using:
> GNU gcc 2.95 shipped with Dev-C++ (gcc -o echo_g.exe echo.c)
> BC++ 5.5 of thge "Borland free command line tools" (bcc32 -eecho_b.exe
> echo.c).
>
> Then I've "touched" the files "foo.c" and "bar.c" and tried
> the following:
>
> command output
> echo_g *.c bar.c foo.c
> echo_b *.c *.c
>
> All of this on Win98SE.
> Is there somebody that can tell what is going on?
> Is this bug(?) common to the shell of other Windows systems too?
I do not understand what you did.
Ioannis
* Ioannis Vranos
* Programming pages: http://www.noicys.d2g.com
* Alternative URL: http://run.to/noicys
|
|
From: <gi...@li...> - 2002-02-24 15:09:26
|
Hello list,
here is one, funny, thing of which I have no explanation:
consider the following program:
/* echo.c */
#include <stdio.h>
int
main(int argc, char **argv)
{
while (--argc)
printf("%s ", *++argv);
return 0;
}
I compiled it using:
GNU gcc 2.95 shipped with Dev-C++ (gcc -o echo_g.exe echo.c)
BC++ 5.5 of thge "Borland free command line tools" (bcc32 -eecho_b.exe
echo.c).
Then I've "touched" the files "foo.c" and "bar.c" and tried the following:
command output
echo_g *.c bar.c foo.c
echo_b *.c *.c
All of this on Win98SE.
Is there somebody that can tell what is going on?
Is this bug(?) common to the shell of other Windows systems too?
TIA
--
gisan
gi...@li...
|
|
From: Yeoh H. <ye...@ya...> - 2002-02-23 23:12:28
|
Hi, You might want to look at BASS. Here's some info. BASS is a sound system for use in Windows software. It's purpose is to = provide developers with a set of powerful yet easy to use sample, stream = (MP3, MP2, MP1, OGG, WAV, custom generated), MOD music (XM, IT, S3M, = MOD, MTM, UMX), MO3 music (MP3/OGG compressed MODs) and audio CD = playback functions. BASS also allows 3D positioning of samples, streams = and MOD musics, and supports EAX (Environmental Audio eXtensions). The URL is http://www.un4seen.com/music/ Regards, Yeoh ~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~ Author of "How to Create an eBook Using Visual C++" Free Downloads at http://www.yeohhs.com ICT eBooks by Yeoh HS ~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~`~ ----- Original Message -----=20 From: Stein Nyg=E5rd=20 To: DevCpp=20 Sent: Sunday, February 24, 2002 6:14 AM Subject: [Dev-C++] multiple sounds? Hi all! =20 Anyone know a site with information about playing multiple sounds? =20 THANKS =20 - stein |
|
From: <ste...@ge...> - 2002-02-23 22:14:21
|
Hi all! Anyone know a site with information about playing multiple sounds? THANKS - stein |
|
From: Yeoh H. <ye...@ya...> - 2002-02-21 01:03:58
|
Hi,
Here's an MSDN article that might be of some help.
<begin MSDN extract>
Serial Communications in Win32
Allen Denver
Microsoft Windows Developer Support
December 11, 1995
Allen seldom eats breakfast, but if he had to pick a favorite, Win32 serial
communications would be the top choice.
Click to open or copy the files in the MTTTY sample application for this
technical article.
Abstract
Serial communications in Microsoft® Win32® is significantly different from
serial communications in 16-bit Microsoft Windows®. Those familiar with
16-bit serial communications functions will have to relearn many parts of
the system to program serial communications properly. This article will help
to accomplish this. Those unfamiliar with serial communications will find
this article a helpful foundation for development efforts.
This article assumes the reader is familiar with the fundamentals of
multiple threading and synchronization in Win32. In addition, a basic
familiarity of the Win32 heap functions is useful to fully comprehend the
memory management methods used by the sample, MTTTY, included with this
article. For more information regarding these functions, consult the Win32
Software Development Kit (SDK) documentation, the Microsoft Win32 SDK
Knowledge Base, or the Microsoft Developer Network Library. Application
programming interfaces (APIs) that control user interface features of
windows and dialog boxes, though not discussed here, are useful to know in
order to fully comprehend the sample provided with this article. Readers
unfamiliar with general Windows programming practices should learn some of
the fundamentals of general Windows programming before taking on serial
communications. In other words, get your feet wet before diving in head
first.
Introduction
The focus of this article is on application programming interfaces (APIs)
and methods that are compatible with Microsoft® Windows NT® and Windows 95;
therefore, APIs supported on both platforms are the only ones discussed.
Windows 95 supports the Win32® Telephony API (TAPI) and Windows NT 3.x does
not; therefore, this discussion will not include TAPI. TAPI does deserve
mention, however, in that it very nicely implements modem interfacing and
call controlling. A production application that works with modems and makes
telephone calls should implement these features using the TAPI interface.
This will allow seamless integration with the other TAPI-enabled
applications that a user may have. Furthermore, this article does not
discuss some of the configuration functions in Win32, such as
GetCommProperties.
The article is broken into the following sections: Opening a port, reading
and writing (nonoverlapped and overlapped), serial status (events and
errors), and serial settings (DCB, flow control, and communications
time-outs).
The sample included with this article, MTTTY: Multithreaded TTY, implements
many of the features discussed here. It uses three threads in its
implementation: a user interface thread that does memory management, a
writer thread that controls all writing, and a reader/status thread that
reads data and handles status changes on the port. The sample employs a few
different data heaps for memory management. It also makes extensive use of
synchronization methods to facilitate communication between threads.
Opening a Port
The CreateFile function opens a communications port. There are two ways to
call CreateFile to open the communications port: overlapped and
nonoverlapped. The following is the proper way to open a communications
resource for overlapped operation:
HANDLE hComm;
hComm = CreateFile( gszPort,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0);
if (hComm == INVALID_HANDLE_VALUE)
// error opening port; abort
Removal of the FILE_FLAG_OVERLAPPED flag from the call to CreateFile
specifies nonoverlapped operation. The next section discusses overlapped and
nonoverlapped operations.
The Win32 Software Development Kit (SDK) Programmer's Reference (Overviews,
Window Management, System Services) states that when opening a
communications port, the call to CreateFile has the following requirements:
fdwShareMode must be zero. Communications ports cannot be shared in the same
manner that files are shared. Applications using TAPI can use the TAPI
functions to facilitate sharing resources between applications. For Win32
applications not using TAPI, handle inheritance or duplication is necessary
to share the communications port. Handle duplication is beyond the scope of
this article; please refer to the Win32 SDK documentation for more
information.
fdwCreate must specify the OPEN_EXISTING flag.
hTemplateFile parameter must be NULL.
One thing to note about port names is that traditionally they have been
COM1, COM2, COM3, or COM4. The Win32 API does not provide any mechanism for
determining what ports exist on a system. Windows NT and Windows 95 keep
track of installed ports differently from one another, so any one method
would not be portable across all Win32 platforms. Some systems even have
more ports than the traditional maximum of four. Hardware vendors and
serial-device-driver writers are free to name the ports anything they like.
For this reason, it is best that users have the ability to specify the port
name they want to use. If a port does not exist, an error will occur
(ERROR_FILE_NOT_FOUND) after attempting to open the port, and the user
should be notified that the port isn't available.
Reading and Writing
Reading from and writing to communications ports in Win32 is very similar to
file input/output (I/O) in Win32. In fact, the functions that accomplish
file I/O are the same functions used for serial I/O. I/O in Win32 can be
done either of two ways: overlapped or nonoverlapped. The Win32 SDK
documentation uses the terms asynchronous and synchronous to connote these
types of I/O operations. This article, however, uses the terms overlapped
and nonoverlapped.
Nonoverlapped I/O is familiar to most developers because this is the
traditional form of I/O, where an operation is requested and is assumed to
be complete when the function returns. In the case of overlapped I/O, the
system may return to the caller immediately even when an operation is not
finished and will signal the caller when the operation completes. The
program may use the time between the I/O request and its completion to
perform some "background" work.
Reading and writing in Win32 is significantly different from reading and
writing serial communications ports in 16-bit Windows. 16-bit Windows only
has the ReadComm and WriteComm functions. Win32 reading and writing can
involve many more functions and choices. These issues are discussed below.
Nonoverlapped I/O
Nonoverlapped I/O is very straightforward, though it has limitations. An
operation takes place while the calling thread is blocked. Once the
operation is complete, the function returns and the thread can continue its
work. This type of I/O is useful for multithreaded applications because
while one thread is blocked on an I/O operation, other threads can still
perform work. It is the responsibility of the application to serialize
access to the port correctly. If one thread is blocked waiting for its I/O
operation to complete, all other threads that subsequently call a
communications API will be blocked until the original operation completes.
For instance, if one thread were waiting for a ReadFile function to return,
any other thread that issued a WriteFile function would be blocked.
One of the many factors to consider when choosing between nonoverlapped and
overlapped operations is portability. Overlapped operation is not a good
choice because most operating systems do not support it. Most operating
systems support some form of multithreading, however, so multithreaded
nonoverlapped I/O may be the best choice for portability reasons.
Overlapped I/O
Overlapped I/O is not as straightforward as nonoverlapped I/O, but allows
more flexibility and efficiency. A port open for overlapped operations
allows multiple threads to do I/O operations at the same time and perform
other work while the operations are pending. Furthermore, the behavior of
overlapped operations allows a single thread to issue many different
requests and do work in the background while the operations are pending.
In both single-threaded and multithreaded applications, some synchronization
must take place between issuing requests and processing the results. One
thread will have to be blocked until the result of an operation is
available. The advantage is that overlapped I/O allows a thread to do some
work between the time of the request and its completion. If no work can be
done, then the only case for overlapped I/O is that it allows for better
user responsiveness.
Overlapped I/O is the type of operation that the MTTTY sample uses. It
creates a thread that is responsible for reading the port's data and reading
the port's status. It also performs periodic background work. The program
creates another thread exclusively for writing data out the port.
Note Applications sometimes abuse multithreading systems by creating too
many threads. Although using multiple threads can resolve many difficult
problems, creating excessive threads is not the most efficient use of them
in an application. Threads are less a strain on the system than processes
but still require system resources such as CPU time and memory. An
application that creates excessive threads may adversely affect the
performance of the entire system. A better use of threads is to create a
different request queue for each type of job and to have a worker thread
issue an I/O request for each entry in the request queue. This method is
used by the MTTTY sample provided with this article.
An overlapped I/O operation has two parts: the creation of the operation and
the detection of its completion. Creating the operation entails setting up
an OVERLAPPED structure, creating a manual-reset event for synchronization,
and calling the appropriate function (ReadFile or WriteFile). The I/O
operation may or may not be completed immediately. It is an error for an
application to assume that a request for an overlapped operation always
yields an overlapped operation. If an operation is completed immediately, an
application needs to be ready to continue processing normally. The second
part of an overlapped operation is to detect its completion. Detecting
completion of the operation involves waiting for the event handle, checking
the overlapped result, and then handling the data. The reason that there is
more work involved with an overlapped operation is that there are more
points of failure. If a nonoverlapped operation fails, the function just
returns an error-return result. If an overlapped operation fails, it can
fail in the creation of the operation or while the operation is pending. You
may also have a time-out of the operation or a time-out waiting for the
signal that the operation is complete.
Reading
The ReadFile function issues a read operation. ReadFileEx also issues a read
operation, but since it is not available on Windows 95, it is not discussed
in this article. Here is a code snippet that details how to issue a read
request. Notice that the function calls a function to process the data if
the ReadFile returns TRUE. This is the same function called if the operation
becomes overlapped. Note the fWaitingOnRead flag that is defined by the
code; it indicates whether or not a read operation is overlapped. It is used
to prevent the creation of a new read operation if one is outstanding.
DWORD dwRead;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
// Create the overlapped event. Must be closed before exiting
// to avoid a handle leak.
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL)
// Error creating overlapped event; abort.
if (!fWaitingOnRead) {
// Issue read operation.
if (!ReadFile(hComm, lpBuf, READ_BUF_SIZE, &dwRead, &osReader)) {
if (GetLastError() != ERROR_IO_PENDING) // read not delayed?
// Error in communications; report it.
else
fWaitingOnRead = TRUE;
}
else
// read completed immediately
HandleASuccessfulRead(lpBuf, dwRead);
}
}
The second part of the overlapped operation is the detection of its
completion. The event handle in the OVERLAPPED structure is passed to the
WaitForSingleObject function, which will wait until the object is signaled.
Once the event is signaled, the operation is complete. This does not mean
that it was completed successfully, just that it was completed. The
GetOverlappedResult function reports the result of the operation. If an
error occurred, GetOverlappedResult returns FALSE and GetLastError returns
the error code. If the operation was completed successfully,
GetOverlappedResult will return TRUE.
Note GetOverlappedResult can detect completion of the operation, as well
as return the operation's failure status. GetOverlappedResult returns FALSE
and GetLastError returns ERROR_IO_INCOMPLETE when the operation is not
completed. In addition, GetOverlappedResult can be made to block until the
operation completes. This effectively turns the overlapped operation into a
nonoverlapped operation and is accomplished by passing TRUE as the bWait
parameter.
Here is a code snippet that shows one way to detect the completion of an
overlapped read operation. Note that the code calls the same function to
process the data that was called when the operation completed immediately.
Also note the use of the fWaitingOnRead flag. Here it controls entry into
the detection code, since it should be called only when an operation is
outstanding.
#define READ_TIMEOUT 500 // milliseconds
DWORD dwRes;
if (fWaitingOnRead) {
dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT);
switch(dwRes)
{
// Read completed.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osReader, &dwRead, FALSE))
// Error in communications; report it.
else
// Read completed successfully.
HandleASuccessfulRead(lpBuf, dwRead);
// Reset flag so that another opertion can be issued.
fWaitingOnRead = FALSE;
break;
case WAIT_TIMEOUT:
// Operation isn't complete yet. fWaitingOnRead flag isn't
// changed since I'll loop back around, and I don't want
// to issue another read until the first one finishes.
//
// This is a good time to do some background work.
break;
default:
// Error in the WaitForSingleObject; abort.
// This indicates a problem with the OVERLAPPED structure's
// event handle.
break;
}
}
Writing
Transmitting data out the communications port is very similar to reading in
that it uses a lot of the same APIs. The code snippet below demonstrates how
to issue and wait for a write operation to be completed.
BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};
DWORD dwWritten;
DWORD dwRes;
BOOL fRes;
// Create this write operation's OVERLAPPED structure's hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
// error creating overlapped event handle
return FALSE;
// Issue write.
if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
if (GetLastError() != ERROR_IO_PENDING)
// WriteFile failed, but isn't delayed. Report error and abort.
fRes = FALSE;
}
else
// Write is pending.
dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
switch(dwRes)
{
// OVERLAPPED structure's event has been signaled.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten,
FALSE))
fRes = FALSE;
else
// Write operation completed successfully.
fRes = TRUE;
break;
default:
// An error has occurred in WaitForSingleObject.
// This usually indicates a problem with the
// OVERLAPPED structure's event handle.
fRes = FALSE;
break;
}
}
}
else
// WriteFile completed immediately.
fRes = TRUE;
CloseHandle(osWrite.hEvent);
return fRes;
}
Notice that the code above uses the WaitForSingleObject function with a
time-out value of INFINITE. This causes the WaitForSingleObject function to
wait forever until the operation is completed; this may make the thread or
program appear to be "hung" when, in fact, the write operation is simply
taking a long time to complete or flow control has blocked the transmission.
Status checking, discussed later, can detect this condition, but doesn't
cause the WaitForSingleObject to return. Three things can alleviate this
condition:
Place the code in a separate thread. This allows other threads to execute
any functions they desire while our writer thread waits for the write to be
completed. This is what the MTTTY sample does.
Use COMMTIMEOUTS to cause the write to be completed after a time-out period
has passed. This is discussed more fully in the "Communications Time-outs"
section later in this article. This is also what the MTTTY sample allows.
Change the WaitForSingleObject call to include a real time-out value. This
causes more problems because if the program issues another operation while
an older operation is still pending, new OVERLAPPED structures and
overlapped events need to be allocated. This type of recordkeeping is
difficult, particularly when compared to using a "job queue" design for the
operations. The "job queue" method is used in the MTTTY sample.
Note: The time-out values in synchronization functions are not
communications time-outs. Synchronization time-outs cause
WaitForSingleObject or WaitForMultipleObjects to return WAIT_TIMEOUT. This
is not the same as a read or write operation timing out. Communications
time-outs are described later in this article.
Because the WaitForSingleObject function in the above code snippet uses an
INFINITE time-out, it is equivalent to using GetOverlappedResult with TRUE
for the fWait parameter. Here is equivalent code in a much simplified form:
BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};
DWORD dwWritten;
BOOL fRes;
// Create this writes OVERLAPPED structure hEvent.
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
// Error creating overlapped event handle.
return FALSE;
// Issue write.
if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
if (GetLastError() != ERROR_IO_PENDING)
// WriteFile failed, but it isn't delayed. Report error and abort.
fRes = FALSE;
}
else {
// Write is pending.
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE))
fRes = FALSE;
else
// Write operation completed successfully.
fRes = TRUE;
}
}
else
// WriteFile completed immediately.
fRes = TRUE;
CloseHandle(osWrite.hEvent);
return fRes;
}
GetOverlappedResult is not always the best way to wait for an overlapped
operation to be completed. For example, if an application needs to wait on
another event handle, the first code snippet serves as a better model than
the second. The call to WaitForSingleObject is easy to change to
WaitForMultipleObjects to include the additional handles on which to wait.
This is what the MTTTY sample application does.
A common mistake in overlapped I/O is to reuse an OVERLAPPED structure
before the previous overlapped operation is completed. If a new overlapped
operation is issued before a previous operation is completed, a new
OVERLAPPED structure must be allocated for it. A new manual-reset event for
the hEvent member of the OVERLAPPED structure must also be created. Once an
overlapped operation is complete, the OVERLAPPED structure and its event are
free for reuse.
The only member of the OVERLAPPED structure that needs modifying for serial
communications is the hEvent member. The other members of the OVERLAPPED
structure should be initialized to zero and left alone. Modifying the other
members of the OVERLAPPED structure is not necessary for serial
communications devices. The documentation for ReadFile and WriteFile state
that the Offset and OffsetHigh members of the OVERLAPPED structure must be
updated by the application, or else results are unpredictable. This
guideline should be applied to OVERLAPPED structures used for other types of
resources, such as files.
Serial Status
There are two methods to retrieve the status of a communications port. The
first is to set an event mask that causes notification of the application
when the desired events occur. The SetCommMask function sets this event
mask, and the WaitCommEvent function waits for the desired events to occur.
These functions are similar to the 16-bit functions SetCommEventMask and
EnableCommNotification, except that the Win32 functions do not post
WM_COMMNOTIFY messages. In fact, the WM_COMMNOTIFY message is not even part
of the Win32 API. The second method for retrieving the status of the
communications port is to periodically call a few different status
functions. Polling is, of course, neither efficient nor recommended.
Communications Events
Communications events can occur at any time in the course of using a
communications port. The two steps involved in receiving notification of
communications events are as follows:
SetCommMask sets the desired events that cause a notification.
WaitCommEvent issues a status check. The status check can be an overlapped
or nonoverlapped operation, just as the read and write operations can be.
Note: The word event in this context refers to communications events only.
It does not refer to an event object used for synchronization.
Here is an example of the SetCommMask function:
DWORD dwStoredFlags;
dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\
EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;
if (!SetCommMask(hComm, dwStoredFlags))
// error setting communications mask
A description of each type of event is in Table 1.
Table 1. Communications Event Flags
Event Flag Description
EV_BREAK A break was detected on input.
EV_CTS The CTS (clear-to-send) signal changed state. To get the actual state
of the CTS line, GetCommModemStatus should be called.
EV_DSR The DSR (data-set-ready) signal changed state. To get the actual
state of the DSR line, GetCommModemStatus should be called.
EV_ERR A line-status error occurred. Line-status errors are CE_FRAME,
CE_OVERRUN, and CE_RXPARITY. To find the cause of the error, ClearCommError
should be called.
EV_RING A ring indicator was detected.
EV_RLSD The RLSD (receive-line-signal-detect) signal changed state. To get
the actual state of the RLSD line, GetCommModemStatus should be called. Note
that this is commonly referred to as the CD (carrier detect) line.
EV_RXCHAR A new character was received and placed in the input buffer. See
the "Caveat" section below for a discussion of this flag.
EV_RXFLAG The event character was received and placed in the input buffer.
The event character is specified in the EvtChar member of the DCB structure
discussed later. The "Caveat" section below also applies to this flag.
EV_TXEMPTY The last character in the output buffer was sent to the serial
port device. If a hardware buffer is used, this flag only indicates that all
data has been sent to the hardware. There is no way to detect when the
hardware buffer is empty without talking directly to the hardware with a
device driver.
After specifying the event mask, the WaitCommEvent function detects the
occurrence of the events. If the port is open for nonoverlapped operation,
then the WaitCommEvent function does not contain an OVERLAPPED structure.
The function blocks the calling thread until the occurrence of one of the
events. If an event never occurs, the thread may block indefinitely.
Here is a code snippet that shows how to wait for an EV_RING event when the
port is open for nonoverlapped operation:
DWORD dwCommEvent;
if (!SetCommMask(hComm, EV_RING))
// Error setting communications mask
return FALSE;
if (!WaitCommEvent(hComm, &dwCommEvent, NULL))
// An error occurred waiting for the event.
return FALSE;
else
// Event has occurred.
return TRUE;
Note The Microsoft Win32 SDK Knowledge Base documents a problem with
Windows 95 and the EV_RING flag. The above code never returns in Windows 95
because the EV_RING event is not detected by the system; Windows NT properly
reports the EV_RING event. Please see the Win32 SDK Knowledge Base for more
information on this bug.
As noted, the code above can be blocked forever if an event never occurs. A
better solution would be to open the port for overlapped operation and wait
for a status event in the following manner:
#define STATUS_CHECK_TIMEOUT 500 // Milliseconds
DWORD dwRes;
DWORD dwCommEvent;
DWORD dwStoredFlags;
BOOL fWaitingOnStat = FALSE;
OVERLAPPED osStatus = {0};
dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\
EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;
if (!SetCommMask(comHandle, dwStoredFlags))
// error setting communications mask; abort
return 0;
osStatus.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osStatus.hEvent == NULL)
// error creating event; abort
return 0;
for ( ; ; ) {
// Issue a status event check if one hasn't been issued already.
if (!fWaitingOnStat) {
if (!WaitCommEvent(hComm, &dwCommEvent, &osStatus)) {
if (GetLastError() == ERROR_IO_PENDING)
bWaitingOnStatusHandle = TRUE;
else
// error in WaitCommEvent; abort
break;
}
else
// WaitCommEvent returned immediately.
// Deal with status event as appropriate.
ReportStatusEvent(dwCommEvent);
}
// Check on overlapped operation.
if (fWaitingOnStat) {
// Wait a little while for an event to occur.
dwRes = WaitForSingleObject(osStatus.hEvent, STATUS_CHECK_TIMEOUT);
switch(dwRes)
{
// Event occurred.
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &osStatus, &dwOvRes,
FALSE))
// An error occurred in the overlapped operation;
// call GetLastError to find out what it was
// and abort if it is fatal.
else
// Status event is stored in the event flag
// specified in the original WaitCommEvent call.
// Deal with the status event as appropriate.
ReportStatusEvent(dwCommEvent);
// Set fWaitingOnStat flag to indicate that a new
// WaitCommEvent is to be issued.
fWaitingOnStat = FALSE;
break;
case WAIT_TIMEOUT:
// Operation isn't complete yet. fWaitingOnStatusHandle
flag
// isn't changed since I'll loop back around and I don't
want
// to issue another WaitCommEvent until the first one
finishes.
//
// This is a good time to do some background work.
DoBackgroundWork();
break;
default:
// Error in the WaitForSingleObject; abort
// This indicates a problem with the OVERLAPPED structure's
// event handle.
CloseHandle(osStatus.hEvent);
return 0;
}
}
}
CloseHandle(osStatus.hEvent);
The code above very closely resembles the code for overlapped reading. In
fact, the MTTTY sample implements its reading and status checking in the
same thread using WaitForMultipleObjects to wait for either the read event
or the status event to become signaled.
There are two interesting side effects of SetCommMask and WaitCommEvent.
First, if the communications port is open for nonoverlapped operation,
WaitCommEvent will be blocked until an event occurs. If another thread calls
SetCommMask to set a new event mask, that thread will be blocked on the call
to SetCommMask. The reason is that the original call to WaitCommEvent in the
first thread is still executing. The call to SetCommMask blocks the thread
until the WaitCommEvent function returns in the first thread. This side
effect is universal for ports open for nonoverlapped I/O. If a thread is
blocked on any communications function and another thread calls a
communications function, the second thread is blocked until the
communications function returns in the first thread. The second interesting
note about these functions is their use on a port open for overlapped
operation. If SetCommMask sets a new event mask, any pending WaitCommEvent
will complete successfully, and the event mask produced by the operation is
NULL.
Caveat
Using the EV_RXCHAR flag will notify the thread that a byte arrived at the
port. This event, used in combination with the ReadFile function, enables a
program to read data only after it is in the receive buffer, as opposed to
issuing a read that waits for the data to arrive. This is particularly
useful when a port is open for nonoverlapped operation because the program
does not need to poll for incoming data; the program is notified of the
incoming data by the occurrence of the EV_RXCHAR event. Initial attempts to
code this solution often produce the following pseudocode, including one
oversight covered later in this section:
DWORD dwCommEvent;
DWORD dwRead;
char chRead;
if (!SetCommMask(hComm, EV_RXCHAR))
// Error setting communications event mask.
for ( ; ; ) {
if (WaitCommEvent(hComm, &dwCommEvent, NULL)) {
if (ReadFile(hComm, &chRead, 1, &dwRead, NULL))
// A byte has been read; process it.
else
// An error occurred in the ReadFile call.
break;
}
else
// Error in WaitCommEvent.
break;
}
The above code waits for an EV_RXCHAR event to occur. When this happens, the
code calls ReadFile to read the one byte received. The loop starts again,
and the code waits for another EV_RXCHAR event. This code works fine when
one or two bytes arrive in quick succession. The byte reception causes the
EV_RXCHAR event to occur. The code reads the byte. If no other byte arrives
before the code calls WaitCommEvent again, then all is fine; the next byte
to arrive will cause the WaitCommEvent function to indicate the occurrence
of the EV_RXCHAR event. If another single byte arrives before the code has a
chance to reach the WaitCommEvent function, then all is fine, too. The first
byte is read as before; the arrival of the second byte causes the EV_RXCHAR
flag to be set internally. When the code returns to the WaitCommEvent
function, it indicates the occurrence of the EV_RXCHAR event and the second
byte is read from the port in the ReadFile call.
The problem with the above code occurs when three or more bytes arrive in
quick succession. The first byte causes the EV_RXCHAR event to occur. The
second byte causes the EV_RXCHAR flag to be set internally. The next time
the code calls WaitCommEvent, it indicates the EV_RXCHAR event. Now, a third
byte arrives at the communications port. This third byte causes the system
to attempt to set the EV_RXCHAR flag internally. Because this has already
occurred when the second byte arrived, the arrival of the third byte goes
unnoticed. The code eventually will read the first byte without a problem.
After this, the code will call WaitCommEvent, and it indicates the
occurrence of the EV_RXCHAR event (from the arrival of the second byte). The
second byte is read, and the code returns to the WaitCommEvent function. The
third byte waits in the system's internal receive buffer. The code and the
system are now out of sync. When a fourth byte finally arrives, the
EV_RXCHAR event occurs, and the code reads a single byte. It reads the third
byte. This will continue indefinitely.
The solution to this problem seems as easy as increasing the number of bytes
requested in the read operation. Instead of requesting a single byte, the
code could request two, ten, or some other number of bytes. The problem with
this idea is that it still fails when two or more extra bytes above the size
of the read request arrive at the port in quick succession. So, if two bytes
are read, then four bytes arriving in quick succession would cause the
problem. Ten bytes requested would still fail if twelve bytes arrived in
quick succession.
The real solution to this problem is to read from the port until no bytes
are remaining. The following pseudocode solves the problem by reading in a
loop until zero characters are read. Another possible method would be to
call ClearCommError to determine the number of bytes in the buffer and read
them all in one read operation. This method requires more sophisticated
buffer management, but it reduces the number of reads when a lot of data
arrives at once.
DWORD dwCommEvent;
DWORD dwRead;
char chRead;
if (!SetCommMask(hComm, EV_RXCHAR))
// Error setting communications event mask
for ( ; ; ) {
if (WaitCommEvent(hComm, &dwCommEvent, NULL)) {
do {
if (ReadFile(hComm, &chRead, 1, &dwRead, NULL))
// A byte has been read; process it.
else
// An error occurred in the ReadFile call.
break;
} while (dwRead);
}
else
// Error in WaitCommEvent
break;
}
The above code does not work correctly without setting the proper time-outs.
Communications time-outs, discussed later, affect the behavior of the
ReadFile operation in order to cause it to return without waiting for bytes
to arrive. Discussion of this topic occurs later in the "Communications
Time-outs" section of this article.
The above caveat regarding EV_RXCHAR also applies to EV_RXFLAG. If flag
characters arrive in quick succession, EV_RXFLAG events may not occur for
all of them. Once again, the best solution is to read all bytes until none
remain.
The above caveat also applies to other events not related to character
reception. If other events occur in quick succession some of the
notifications will be lost. For instance, if the CTS line voltage starts
high, then goes low, high, and low again, an EV_CTS event occurs. There is
no guarantee of how many EV_CTS events will actually be detected with
WaitCommEvent if the changes in the CTS line happen quickly. For this
reason, WaitCommEvent cannot be used to keep track of the state of the line.
Line status is covered in the "Modem Status" section later in this article.
Error Handling and Communications Status
One of the communications event flags specified in the call to SetCommMask
is possibly EV_ERR. The occurrence of the EV_ERR event indicates that an
error condition exists in the communications port. Other errors can occur in
the port that do not cause the EV_ERR event to occur. In either case, errors
associated with the communications port cause all I/O operations to be
suspended until removal of the error condition. ClearCommError is the
function to call to detect errors and clear the error condition.
ClearCommError also provides communications status indicating why
transmission has stopped; it also indicates the number of bytes waiting in
the transmit and receive buffers. The reason why transmission may stop is
because of errors or to flow control. The discussion of flow control occurs
later in this article.
Here is some code that demonstrates how to call ClearCommError:
COMSTAT comStat;
DWORD dwErrors;
BOOL fOOP, fOVERRUN, fPTO, fRXOVER, fRXPARITY, fTXFULL;
BOOL fBREAK, fDNS, fFRAME, fIOE, fMODE;
// Get and clear current errors on the port.
if (!ClearCommError(hComm, &dwErrors, &comStat))
// Report error in ClearCommError.
return;
// Get error flags.
fDNS = dwErrors & CE_DNS;
fIOE = dwErrors & CE_IOE;
fOOP = dwErrors & CE_OOP;
fPTO = dwErrors & CE_PTO;
fMODE = dwErrors & CE_MODE;
fBREAK = dwErrors & CE_BREAK;
fFRAME = dwErrors & CE_FRAME;
fRXOVER = dwErrors & CE_RXOVER;
fTXFULL = dwErrors & CE_TXFULL;
fOVERRUN = dwErrors & CE_OVERRUN;
fRXPARITY = dwErrors & CE_RXPARITY;
// COMSTAT structure contains information regarding
// communications status.
if (comStat.fCtsHold)
// Tx waiting for CTS signal
if (comStat.fDsrHold)
// Tx waiting for DSR signal
if (comStat.fRlsdHold)
// Tx waiting for RLSD signal
if (comStat.fXoffHold)
// Tx waiting, XOFF char rec'd
if (comStat.fXoffSent)
// Tx waiting, XOFF char sent
if (comStat.fEof)
// EOF character received
if (comStat.fTxim)
// Character waiting for Tx; char queued with TransmitCommChar
if (comStat.cbInQue)
// comStat.cbInQue bytes have been received, but not read
if (comStat.cbOutQue)
// comStat.cbOutQue bytes are awaiting transfer
Modem Status (a.k.a. Line Status)
The call to SetCommMask may include the flags EV_CTS, EV_DSR, EV_RING, and
EV_RLSD. These flags indicate changes in the voltage on the lines of the
serial port. There is no indication of the actual status of these lines,
just that a change occurred. The GetCommModemStatus function retrieves the
actual state of these status lines by returning a bit mask indicating a 0
for low or no voltage and 1 for high voltage for each of the lines.
Please note that the term RLSD (Receive Line Signal Detect) is commonly
referred to as the CD (Carrier Detect) line.
Note The EV_RING flag does not work in Windows 95 as mentioned earlier.
The GetCommModemStatus function, however, does detect the state of the RING
line.
Changes in these lines may also cause a flow-control event. The
ClearCommError function reports whether transmission is suspended because of
flow control. If necessary, a thread may call ClearCommError to detect
whether the event is the cause of a flow-control action. Flow control is
covered in the "Flow Control" section later in this article.
Here is some code that demonstrates how to call GetCommModemStatus:
DWORD dwModemStatus;
BOOL fCTS, fDSR, fRING, fRLSD;
if (!GetCommModemStatus(hComm, &dwModemStatus))
// Error in GetCommModemStatus;
return;
fCTS = MS_CTS_ON & dwModemStatus;
fDSR = MS_DSR_ON & dwModemStatus;
fRING = MS_RING_ON & dwModemStatus;
fRLSD = MS_RLSD_ON & dwModemStatus;
// Do something with the flags.
Extended Functions
The driver will automatically change the state of control lines as
necessary. Generally speaking, changing status lines is under the control of
a driver. If a device uses communications port control lines in a manner
different from RS-232 standards, the standard serial communications driver
will not work to control the device. If the standard serial communications
driver will not control the device, a custom device driver is necessary.
There are occasions when standard control lines are under the control of the
application instead of the serial communications driver. For instance, an
application may wish to implement its own flow control. The application
would be responsible for changing the status of the RTS and DTR lines.
EscapeCommFunction directs a communications driver to perform such extended
operations. EscapeCommFunction can make the driver perform some other
function, such as setting or clearing a BREAK condition. For more
information on this function, consult the Win32 SDK documentation, the
Microsoft Win32 SDK Knowledge Base, or the Microsoft Developer Network
(MSDN) Library.
Serial Settings
DCB Settings
The most crucial aspect of programming serial communications applications is
the settings in the Device-Control Block (DCB) structure. The most common
errors in serial communications programming occur in initializing the DCB
structure improperly. When the serial communications functions do not behave
as expected, a close examination of the DCB structure usually reveals the
problem.
There are three ways to initialize a DCB structure. The first method is to
use the function GetCommState. This function returns the current DCB in use
for the communications port. The following code shows how to use the
GetCommState function:
DCB dcb = {0};
if (!GetCommState(hComm, &dcb))
// Error getting current DCB settings
else
// DCB is ready for use.
The second method to initialize a DCB is to use a function called
BuildCommDCB. This function fills in the baud, parity type, number of stop
bits, and number of data bits members of the DCB. The function also sets the
flow-control members to default values. Consult the documentation of the
BuildCommDCB function for details on which default values it uses for
flow-control members. Other members of the DCB are unaffected by this
function. It is the program's duty to make sure the other members of the DCB
do not cause errors. The simplest thing to do in this regard is to
initialize the DCB structure with zeros and then set the size member to the
size, in bytes, of the structure. If the zero initialization of the DCB
structure does not occur, then there may be nonzero values in the reserved
members; this produces an error when trying to use the DCB later. The
following function shows how to properly use this method:
DCB dcb;
FillMemory(&dcb, sizeof(dcb), 0);
dcb.DCBlength = sizeof(dcb);
if (!BuildCommDCB("9600,n,8,1", &dcb))
// Couldn't build the DCB. Usually a problem
// with the communications specification string.
return FALSE;
}
else
// DCB is ready for use.
The third method to initialize a DCB structure is to do it manually. The
program allocates the DCB structure and sets each member with any value
desired. This method does not deal well with changes to the DCB in future
implementations of Win32 and is not recommended.
An application usually needs to set some of the DCB members differently than
the defaults or may need to modify settings in the middle of execution. Once
proper initialization of the DCB occurs, modification of individual members
is possible. The changes to the DCB structure do not have any effect on the
behavior of the port until execution of the SetCommState function. Here is a
section of code that retrieves the current DCB, changes the baud, and then
attempts to set the configuration:
DCB dcb;
FillMemory(&dcb, sizeof(dcb), 0);
if (!GetCommState(hComm, &dcb)) // get current DCB
// Error in GetCommState
return FALSE;
// Update DCB rate.
dcb.BaudRate = CBR_9600 ;
// Set new state.
if (!SetCommState(hComm, &dcb))
// Error in SetCommState. Possibly a problem with the communications
// port handle or a problem with the DCB structure itself.
Here is an explanation of each of the members of the DCB and how they affect
other parts of the serial communications functions.
Note Most of this information is from the Win32 SDK documentation. Because
documentation is the official word in what the members actually are and what
they mean, this table may not be completely accurate if changes occur in the
operating system.
Table 2. The DCB Structure Members
Member Description
DCBlength Size, in bytes, of the structure. Should be set before calling
SetCommState to update the settings.
BaudRate Specifies the baud at which the communications device operates.
This member can be an actual baud value, or a baud index.
fBinary Specifies whether binary mode is enabled. The Win32 API does not
support nonbinary mode transfers, so this member should be TRUE. Trying to
use FALSE will not work.
fParity Specifies whether parity checking is enabled. If this member is
TRUE, parity checking is performed and parity errors are reported. This
should not be confused with the Parity member, which controls the type of
parity used in communications.
fOutxCtsFlow Specifies whether the CTS (clear-to-send) signal is monitored
for output flow control. If this member is TRUE and CTS is low, output is
suspended until CTS is high again. The CTS signal is under control of the
DCE (usually a modem), the DTE (usually the PC) simply monitors the status
of this signal, the DTE does not change it.
fOutxDsrFlow Specifies whether the DSR (data-set-ready) signal is monitored
for output flow control. If this member is TRUE and DSR is low, output is
suspended until DSR is high again. Once again, this signal is under the
control of the DCE; the DTE only monitors this signal.
fDtrControl Specifies the DTR (data-terminal-ready) input flow control. This
member can be one of the following values:
Value Meaning
DTR_CONTROL_DISABLE Lowers the DTR line when the device is opened. The
application can adjust the state of the line with EscapeCommFunction.
DTR_CONTROL_ENABLE Raises the DTR line when the device is opened. The
application can adjust the state of the line with EscapeCommFunction.
DTR_CONTROL_HANDSHAKE Enables DTR flow-control handshaking. If this value
is used, it is an error for the application to adjust the line with
EscapeCommFunction.
fDsrSensitivity Specifies whether the communications driver is sensitive to
the state of the DSR signal. If this member is TRUE, the driver ignores any
bytes received, unless the DSR modem input line is high.
fTXContinueOnXoff Specifies whether transmission stops when the input buffer
is full and the driver has transmitted the XOFF character. If this member is
TRUE, transmission continues after the XOFF character has been sent. If this
member is FALSE, transmission does not continue until the input buffer is
within XonLim bytes of being empty and the driver has transmitted the XON
character.
fOutX Specifies whether XON/XOFF flow control is used during transmission.
If this member is TRUE, transmission stops when the XOFF character is
received and starts again when the XON character is received.
fInX Specifies whether XON/XOFF flow control is used during reception. If
this member is TRUE, the XOFF character is sent when the input buffer comes
within XoffLim bytes of being full, and the XON character is sent when the
input buffer comes within XonLim bytes of being empty.
fErrorChar Specifies whether bytes received with parity errors are replaced
with the character specified by the ErrorChar member. If this member is TRUE
and the fParity member is TRUE, replacement occurs.
fNull Specifies whether null bytes are discarded. If this member is TRUE,
null bytes are discarded when received.
fRtsControl Specifies the RTS (request-to-send) input flow control. If this
value is zero, the default is RTS_CONTROL_HANDSHAKE. This member can be one
of the following values:
Value Meaning
RTS_CONTROL_DISABLE Lowers the RTS line when the device is opened. The
application can use EscapeCommFunction to change the state of the line.
RTS_CONTROL_ENABLE Raises the RTS line when the device is opened. The
application can use EscapeCommFunction to change the state of the line.
RTS_CONTROL_HANDSHAKE Enables RTS flow-control handshaking. The driver
raises the RTS line, enabling the DCE to send, when the input buffer has
enough room to receive data. The driver lowers the RTS line, preventing the
DCE to send, when the input buffer does not have enough room to receive
data. If this value is used, it is an error for the application to adjust
the line with EscapeCommFunction.
RTS_CONTROL_TOGGLE Specifies that the RTS line will be high if bytes are
available for transmission. After all buffered bytes have been sent, the RTS
line will be low. If this value is set, it would be an error for an
application to adjust the line with EscapeCommFunction. This value is
ignored in Windows 95; it causes the driver to act as if RTS_CONTROL_ENABLE
were specified.
fAbortOnError Specifies whether read and write operations are terminated if
an error occurs. If this member is TRUE, the driver terminates all read and
write operations with an error status (ERROR_IO_ABORTED) if an error occurs.
The driver will not accept any further communications operations until the
application has acknowledged the error by calling the ClearCommError
function.
fDummy2 Reserved; do not use.
wReserved Not used; must be set to zero.
XonLim Specifies the minimum number of bytes allowed in the input buffer
before the XON character is sent.
XoffLim Specifies the maximum number of bytes allowed in the input buffer
before the XOFF character is sent. The maximum number of bytes allowed is
calculated by subtracting this value from the size, in bytes, of the input
buffer.
Parity Specifies the parity scheme to be used. This member can be one of the
following values:
Value Meaning
EVENPARITY Even
MARKPARITY Mark
NOPARITY No parity
ODDPARITY Odd
StopBits Specifies the number of stop bits to be used. This member can be
one of the following values:
Value Meaning
ONESTOPBIT 1 stop bit
ONE5STOPBITS 1.5 stop bits
TWOSTOPBITS 2 stop bits
XonChar Specifies the value of the XON character for both transmission and
reception.
XoffChar Specifies the value of the XOFF character for both transmission and
reception.
ErrorChar Specifies the value of the character used to replace bytes
received with a parity error.
EofChar Specifies the value of the character used to signal the end of data.
EvtChar Specifies the value of the character used to cause the EV_RXFLAG
event. This setting does not actually cause anything to happen without the
use of EV_RXFLAG in the SetCommMask function and the use of WaitCommEvent.
wReserved1 Reserved; do not use.
Flow Control
Flow control in serial communications provides a mechanism for suspending
communications while one of the devices is busy or for some reason cannot do
any communication. There are traditionally two types of flow control:
hardware and software.
A common problem with serial communications is write operations that
actually do not write the data to the device. Often, the problem lies in
flow control being used when the program did not specify it. A close
examination of the DCB structure reveals that one or more of the following
members may be TRUE: fOutxCtsFlow, fOutxDsrFlow, or fOutX. Another mechanism
to reveal that flow control is enabled is to call ClearCommError and examine
the COMSTAT structure. It will reveal when transmission is suspended because
of flow control.
Before discussing the types of flow control, a good understanding of some
terms is in order. Serial communications takes place between two devices.
Traditionally, there is a PC and a modem or printer. The PC is labeled the
Data Terminal Equipment (DTE). The DTE is sometimes called the host. The
modem, printer, or other peripheral equipment is identified as the Data
Communications Equipment (DCE). The DCE is sometimes referred to as the
device.
Hardware flow control
Hardware flow control uses voltage signals on control lines of the serial
cable to control whether sending or receiving is enabled. The DTE and the
DCE must agree on the types of flow control used for a communications
session. Setting the DCB structure to enable flow control just configures
the DTE. The DCE also needs configuration to make certain the DTE and DCE
use the same type of flow control. There is no mechanism provided by Win32
to set the flow control of the DCE. DIP switches on the device, or commands
sent to it typically establish its configuration. The following table
describes the control lines, the direction of the flow control, and the
line's effect on the DTE and DCE.
Table 3. Hardware Flow-control Lines
Line and Direction Effect on DTE/DCE
CTS
(Clear To Send)
Output flow control DCE sets the line high to indicate that it can receive
data. DCE sets the line low to indicate that it cannot receive data.
If the fOutxCtsFlow member of the DCB is TRUE, then the DTE will not send
data if this line is low. It will resume sending if the line is high.
If the fOutxCtsFlow member of the DCB is FALSE, then the state of the line
does not affect transmission.
DSR
(Data Set Ready)
Output flow control DCE sets the line high to indicate that it can receive
data. DCE sets the line low to indicate that it cannot receive data.
If the fOutxDsrFlow member of the DCB is TRUE, then the DTE will not send
data if this line is low. It will resume sending if the line is high.
If the fOutxDsrFlow member of the DCB is FALSE, then the state of the line
does not affect transmission.
DSR
(Data Set Ready)
Input flow control If the DSR line is low, then data that arrives at the
port is ignored. If the DSR line is high, data that arrives at the port is
received.
This behavior occurs if the fDsrSensitivity member of the DCB is set to
TRUE. If it is FALSE, then the state of the line does not affect reception.
RTS
(Ready To Send)
Input flow control The RTS line is controlled by the DTE.
If the fRtsControl member of the DCB is set to RTS_CONTROL_HANDSHAKE, the
following flow control is used: If the input buffer has enough room to
receive data (at least half the buffer is empty), the driver sets the RTS
line high. If the input buffer has little room for incoming data (less than
a quarter of the buffer is empty), the driver sets the RTS line low.
If the fRtsControl member of the DCB is set to RTS_CONTROL_TOGGLE, the
driver sets the RTS line high when data is available for sending. The driver
sets the line low when no data is available for sending. Windows 95 ignores
this value and treats it the same as RTS_CONTROL_ENABLE.
If the fRtsControl member of the DCB is set to RTS_CONTROL_ENABLE or
RTS_CONTROL_DISABLE, the application is free to change the state of the line
as it needs. Note that in this case, the state of the line does not affect
reception.
The DCE will suspend transmission when the line goes low. The DCE will
resume transmission when the line goes high.
DTR
(Data Terminal Ready)
Input flow control The DTR line is controlled by the DTE.
If the fDtrControl member of the DCB is set to DTR_CONTROL_HANDSHAKE, the
following flow control is used: If the input buffer has enough room to
receive data (at least half the buffer is empty), the driver sets the DTR
line high. If the input buffer has little room for incoming data (less than
a quarter of the buffer is empty), the driver sets the DTR line low.
If the fDtrControl member of the DCB is set to DTR_CONTROL_ENABLE or
DTR_CONTROL_DISABLE, the application is free to change the state of the line
as it needs. In this case, the state of the line does not affect reception.
The DCE will suspend transmission when the line goes low. The DCE will
resume transmission when the line goes high.
The need for flow control is easy to recognize when the CE_RXOVER error
occurs. This error indicates an overflow of the receive buffer and data
loss. If data arrives at the port faster than it is read, CE_RXOVER can
occur. Increasing the input buffer size may cause the error to occur less
frequently, but it does not completely solve the problem. Input flow control
is necessary to completely alleviate this problem. When the driver detects
that the input buffer is nearly full, it will lower the input flow-control
lines. This should cause the DCE to stop transmitting, which gives the DTE
enough time to read the data from the input buffer. When the input buffer
has more room available, the voltage on flow-control lines is set high, and
the DCE resumes sending data.
A similar error is CE_OVERRUN. This error occurs when new data arrives
before the communications hardware and serial communications driver
completely receives old data. This can occur when the transmission speed is
too high for the type of communications hardware or CPU. This can also occur
when the operating system is not free to service the communications
hardware. The only way to alleviate this problem is to apply some
combination of decreasing the transmission speed, replacing the
communications hardware, and increasing the CPU speed. Sometimes third-party
hardware drivers that are not very efficient with CPU resources cause this
error. Flow control cannot completely solve the problems that cause the
CE_OVERRUN error, although it may help to reduce the frequency of the error.
Software flow control
Software flow control uses data in the communications stream to control the
transmission and reception of data. Because software flow control uses two
special characters, XOFF and XON, binary transfers cannot use software flow
control; the XON or XOFF character may appear in the binary data and would
interfere with data transfer. Software flow control befits text-based
communications or data being transferred that does not contain the XON and
XOFF characters.
In order to enable software flow control, the fOutX and fInX members of the
DCB must be set to TRUE. The fOutX member controls output flow control. The
fInX member controls input flow control.
One thing to note is that the DCB allows the program to dynamically assign
the values the system recognizes as flow-control characters. The XoffChar
member of the DCB dictates the XOFF character for both input and output flow
control. The XonChar member of the DCB similarly dictates the XON character.
For input flow control, the XoffLim member of the DCB specifies the minimum
amount of free space allowed in the input buffer before the XOFF character
is sent. If the amount of free space in the input buffer drops below this
amount, then the XOFF character is sent. For input flow control, the XonLim
member of the DCB specifies the minimum number of bytes allowed in the input
buffer before the XON character is sent. If the amount of data in the input
buffer drops below this value, then the XON character is sent.
Table 4 lists the behavior of the DTE when using XOFF/XON flow control.
Table 4. Software flow-control behavior
Flow-control character Behavior
XOFF received by DTE DTE transmission is suspended until XON is received.
DTE reception continues. The fOutX member of the DCB controls this behavior.
XON received by DTE If DTE transmission is suspended because of a previous
XOFF character being received, DTE transmission is resumed. The fOutX member
of the DCB controls this behavior.
XOFF sent from DTE XOFF is automatically sent by the DTE when the receive
buffer approaches full. The actual limit is dictated by the XoffLim member
of the DCB. The fInX member of the DCB controls this behavior. DTE
transmission is controlled by the fTXContinueOnXoff member of the DCB as
described below.
XON sent from the DTE XON is automatically sent by the DTE when the receive
buffer approaches empty. The actual limit is dictated by the XonLim member
of the DCB. The fInX member of the DCB controls this behavior.
If software flow control is enabled for input control, then the
fTXContinueOnXoff member of the DCB takes effect. The fTXContinueOnXoff
member controls whether transmission is suspended after the XOFF character
is automatically sent by the system. If fTXContinueOnXoff is TRUE, then
transmission continues after the XOFF is sent when the receive buffer is
full. If fTXContinueOnXoff is FALSE, then transmission is suspended until
the system automatically sends the XON character. DCE devices using software
flow control will suspend their sending after the XOFF character is
received. Some equipment will resume sending when the XON character is sent
by the DTE. On the other hand, some DCE devices will resume sending after
any character arrives. The fTXContinueOnXoff member should be set to FALSE
when communicating with a DCE device that resumes sending after any
character arrives. If the DTE continued transmission after it automatically
sent the XOFF, the resumption of transmission would cause the DCE to
continue sending, defeating the XOFF.
There is no mechanism available in the Win32 API to cause the DTE to behave
the same way as these devices. The DCB structure contains no members for
specifying suspended transmission to resume when any character is received.
The X...
[truncated message content] |