Get_line and cygwin

From: Patrick Dughi (
Date: 01/05/02

        While trying to figure out if it really is more memory conscious
to run a version of Circle with gcc vs. MSVC, I discovered a minor problem
... uhm.. that will cause cygwin versions of circle30bpl19 to not work
altogether. ....

        Like a friend said: "It will run fine once I take care of this
minor crash bug." The definition of minor must be relative.

So, here's the skinny;
        Under MSVC 6, fgets works as you'd think it would if you were
dependant upon a smart library.. choosing 'newline' to be both '\r' and
'\n' - and apparently accepted junctions.  Thus, fgetting a line like
"S\r\n" would return "S\n", which upon passing through the get_file()
function is returned as 'S'.

        Apparently this is how it works in most *nix environments as well.

        Under cygwin v., using gcc version 2.95.3-5 (cygwin
special) fgets works in the way it's described literally in the
documentation; ie, newline = '\n' and that's it.  So, fgetting a line like
"S\r\n" would return "S\r\n" and when get_file returns it, it will be

        Boooooo! Hissss! Baaad!

        Because this means that S is never counted as a proper instruction
in a zon file (S is only valid if the buffer from get_line is exactly
equal to "S\0").  This means the zone command count is off by one. Etc.
Etc. Etc.  This code is repeated through out, so, it was easier to just
change get_line to match the intended behavior.

        So, you need to do a little rewrite, and due to the way get_line
is guarenteed to get either a) A line with something in it, or b) return
0, you have a big problem.

        This is because get_line guarentees it will return either a valid
line or a '0' - letting you know it is the end of the file.  So, this

  do {
    if (!fgets(temp, 256, fl))
      return (0);
  } while (*temp == '*' || *temp == '\n');

        Has to be changed to this loop :

  do {
    if (!fgets(temp, 256, fl))
      return (0);
  } while (*temp == '*' || *temp == '\n' || *temp =='\r');

  However, you're not out of the woods yet.  Further on, the trailing \n
is removed.  But we want ALL trailing \r's or \n's removed, regardless of
order.  Removing them is not so hard.

  sl = strlen(temp);
  if (sl > 0 && temp[sl - 1] == '\n')
    temp[sl - 1] = '\0';

        To ->

  while(strlen(temp) > 0 && (temp[strlen(temp)-1] == '\n' ||
                                        temp[strlen(temp)-1] == '\r')) {
    temp[strlen(temp)-1] = '\0';

Thanks to the initial do-while loop, you should be guarenteed to not have
a line which is completely derived of all \r's or \n's at this point, so
you'll never send back a line which is not valid (a NULL string).

The completed (working) version looks like this, and it seems to be
compatible with other non-cygwin versions:

int get_line(FILE *fl, char *buf)
  char temp[256];
  int lines = 0;

  do {
    if (!fgets(temp, 256, fl))
      return (0);
  } while (*temp == '*' || *temp == '\n' || *temp =='\r');

  /* Last line of file doesn't always have a \n, but it should. */

  while(strlen(temp) > 0 && (temp[strlen(temp)-1] == '\n' ||
                                temp[strlen(temp)-1] == '\r')) {
    temp[strlen(temp)-1] = '\0';

/*  not necessary, as this case should NEVER happen
  if(strlen(temp) == 0) {
    return (get_line(fl,buf));

  strcpy(buf, temp);
  return (lines);

        Think that's about it.  Circle seems happy after that.


ps: noted some minor pseduo-problems in the world files for stock 30bpl19,
the terminator for the 0.zon file is $~, whereas most others are just $.
Also, towards the end of both 25.obj and 35.obj (perhaps others) there's a
blank line before the closing indicator (S, though it's pretty synonymous
with $, in most code, reading $ is skipped altogether if S is found!).
While this doesn't cause a problem with a working fgets (which will ignore
the line in the do-while loop), again, it's a problem in this case.

I don't believe that arbitrairyly inserted whitespace is a valid part of
the .obj (and others) syntax...

   | FAQ: |
   | Archives: |
   | Newbie List:   |

This archive was generated by hypermail 2b30 : 06/25/03 PDT