[AD] Demo game bug

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


There appears to be a bug in the demo game, caused by the mac
port (!).  The demo game scans all the source files for author
names in order to do the credit display.  However, the mac files
are in mac format, having no linefeeds at all, and this is
causing problems in pack_fgets.  The single-line effect it
generates overflows the buffer provided by the demo game, and
pack_fgetc rightly stops adding to the buffer but neglects to
null-terminate it.

However, there are greater problems in pack_fgets -- it also
discards the remainder of the line, and has a 512-character
maximum which is unnecessary.  I've rewritten it to remove the
limit and make it behave better.  While I was there, I also made
it support Mac text format too.

I've preserved the discrepency between fgets and pack_fgets
(fgets copies the newline to your buffer; pack_fgets never has)
because people are surely relying on this bug/feature by now.

The new version requires a pack_ungetc function, which I
provided.  It's static at the moment; I don't know whether it
should be added to the API or not.  It's only safe to call it
immediately after pack_getc, because of buffering issues, and it
doesn't check that this is how you have called it.

I'm attaching the patch, which I have applied to CVS already.

George

-- 
Random project update:
06/03/2001: AllegroGL 0.0.10 released at http://allegrogl.sourceforge.net/
	Six months' worth of changes, including Mingw32 support!

Index: file.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/file.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -u -r1.11 -r1.12
--- file.c	2001/04/19 03:38:40	1.11
+++ file.c	2001/05/07 00:25:44	1.12
@@ -1839,37 +1839,66 @@
 
 
 
+/* pack_ungetc:
+ *  Puts a character back in the file's input buffer.  Added by gfoot for
+ *  use in the fgets function; maybe it should be in the API.  It only works
+ *  for characters just fetched by pack_getc.
+ */
+static void pack_ungetc (int ch, PACKFILE *f)
+{
+   *(--f->buf_pos) = (unsigned char) ch;
+   f->buf_size++;
+   f->flags &= ~PACKFILE_FLAG_EOF;
+}
+
+
+
 /* pack_fgets:
  *  Reads a line from a text file, storing it at location p. Stops when a
  *  linefeed is encountered, or max characters have been read. Returns a
  *  pointer to where it stored the text, or NULL on error. The end of line
- *  is handled by detecting '\n' characters: '\r' is simply ignored.
+ *  is handled by detecting optional '\r' characters optionally followed 
+ *  by '\n' characters. This supports CR-LF (DOS/Windows), LF (Unix), and
+ *  CR (Mac) formats.
  */
 char *pack_fgets(char *p, int max, PACKFILE *f)
 {
-   char buf[512];
-   int pos = 0;
+   char *pmax = p+max - ucwidth(0);
    int c;
-
+   
    if (pack_feof(f)) {
-      usetc(p, 0);
+      if (ucwidth(0) < max) usetc (p,0);
       return NULL;
    }
 
-   while (pos < (int)sizeof(buf)) {
-      c = pack_getc(f);
-      if ((c == '\n') || (c == EOF))
+   while ((c = pack_getc (f)) != EOF) {
+
+      if (c == '\r' || c == '\n') {
+	 /* Technically we should check there's space in the buffer, and if so,
+	  * add a \n.  But pack_fgets has never done this. */
+	 if (c == '\r') {
+	    /* eat the following \n, if any */
+	    if ((c = pack_getc (f)) != '\n') pack_ungetc (c, f);
+	 }
+	 break;
+      }
+
+      /* is there room in the buffer? */
+      if (ucwidth(c) > pmax - p) {
+	 pack_ungetc (c, f);
+	 c = '\0';
 	 break;
-      else if (c != '\r')
-	 buf[pos++] = c;
+      }
+
+      /* write the character */
+      p += usetc (p, c);
    }
 
-   buf[pos] = 0;
+   /* terminate the string */
+   usetc (p, 0);
 
-   if (*allegro_errno)
+   if (c == '\0' || *allegro_errno)
       return NULL;
-
-   ustrncpy(p, uconvert(buf, U_UTF8, NULL, U_CURRENT, -1), max-ucwidth(0));
 
    return p;
 }


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/