From: fredex AT fcshome DOT stoneham DOT ma DOT us Message-Id: <199606140134.VAA06883@fcshome.stoneham.ma.us> Subject: Re: Behavior of fscanf in V2 To: acmq AT coe DOT ufrj DOT br (Antonio Carlos Moreirao de Queiroz) Date: Thu, 13 Jun 1996 21:34:21 -0400 (EDT) Cc: djgpp AT delorie DOT com In-Reply-To: <199606131829.PAA00693@coe.ufrj.br> from "Antonio Carlos Moreirao de Queiroz" at Jun 13, 96 03:29:30 pm Content-Type: text Content-Length: 9427 Thinking furiously, Antonio Carlos Moreirao de Queiroz wrote: > > > Hi, > > In djgpp V1, in Borland C, or in UNIX gnu C (Sun), I use a statement as: > > while (fscanf(archive,"%s",str1)!=EOF) {...} >... > In djgpp V2 this is apparently not happening. fscanf reads again and again > an empty line after the last item read... > Exactly the same code works with the other compilers. > Is this some bug, or am I doing something "nonstandard"? Sounds somewhat like a bug I encountered recently in the scanf family. Someone sent me a patch for it which I applied to the library sources, recompiled, and voila! it's fixed. The problem I encountered was that fscanf was returning a non-zero, positive value even if the first token on the input line did not match the first item in the format string, causing the parser to mis-diagnose the contents of the input stream. I've got the patched library module (doscan.c) whhich I'll append below for you to try. You'll need the library sources on your machine to compile this. Fred ------------------ /djgpp/src/libc/ansi/stdio/doscan.c ------------------ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #define SPC 01 #define STP 02 #define SHORT 0 #define REGULAR 1 #define LONG 2 #define LONGDOUBLE 4 #define INT 0 #define FLOAT 1 static int _innum(int **ptr, int type, int len, int size, FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr); static int _instr(char *ptr, int type, int len, FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr); static const char *_getccl(const unsigned char *s); static char _sctab[256] = { 0,0,0,0,0,0,0,0, 0,SPC,SPC,SPC,SPC,SPC,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, SPC,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, }; static int nchars = 0; int _doscan(FILE *iop, const char *fmt, void **argp) { return(_doscan_low(iop, fgetc, ungetc, fmt, argp)); } int _doscan_low(FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), const char *fmt, void **argp) { register int ch; int nmatch, len, ch1; int **ptr, fileended, size; nchars = 0; nmatch = 0; fileended = 0; for (;;) switch (ch = *fmt++) { case '\0': return (nmatch); case '%': if ((ch = *fmt++) == '%') goto def; if (ch == 'n') { **(int **)argp++ = nchars; break; } if (fileended) return(nmatch? nmatch: -1); ptr = 0; if (ch != '*') ptr = (int **)argp++; else ch = *fmt++; len = 0; size = REGULAR; while (isdigit(ch)) { len = len*10 + ch - '0'; ch = *fmt++; } if (len == 0) len = 30000; if (ch=='l') { size = LONG; ch = *fmt++; } else if (ch=='h') { size = SHORT; ch = *fmt++; } else if (ch=='L') { size = LONGDOUBLE; ch = *fmt++; } else if (ch=='[') fmt = _getccl((const unsigned char *)fmt); if (isupper(ch)) { /* ch = tolower(ch); gcc gives warning: ANSI C forbids braced groups within expressions */ ch += 'a' - 'A'; size = LONG; } if (ch == '\0') return(-1); if (_innum(ptr, ch, len, size, iop, scan_getc, scan_ungetc, &fileended)) { /* HBB: returns true on successful match */ if (ptr) nmatch++; /* HBB: successful match, and no 'dummy' "%*" spec */ break; /* HBB: success, so go on scanning */ } else if (fileended && !nmatch) return(-1); /* HBB: input failure before any successful match, requests EOF-return */ else return(nmatch); /* HBB: 'normal' failure (matching ~, or input ~ after some successful match(es) */ case ' ': case '\n': case '\t': case '\r': case '\f': case '\v': while (((nchars++, ch1 = scan_getc(iop))!=EOF) && (_sctab[ch1] & SPC)) ; if (ch1 != EOF) { scan_ungetc(ch1, iop); } nchars--; break; default: def: ch1 = scan_getc(iop); if (ch1 != EOF) nchars++; if (ch1 != ch) { if (ch1==EOF) return(nmatch?nmatch:-1); /* HBB: only return -1 if *no* success at all */ scan_ungetc(ch1, iop); nchars--; return(nmatch); } } } static int _innum(int **ptr, int type, int len, int size, FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr) { register char *np; char numbuf[64]; register c, base; int expseen, scale, negflg, c1, ndigit; long lcval; int cpos; if (type=='c' || type=='s' || type=='[') return(_instr(ptr? *(char **)ptr: (char *)NULL, type, len, iop, scan_getc, scan_ungetc, eofptr)); lcval = 0; ndigit = 0; scale = INT; if (type=='e'||type=='f'||type=='g') scale = FLOAT; base = 10; if (type=='o') base = 8; else if (type=='x') base = 16; np = numbuf; expseen = 0; negflg = 0; while (((nchars++, c = scan_getc(iop)) != EOF) && (_sctab[c] & SPC)) ; if (c == EOF) nchars--; if (c=='-') { negflg++; *np++ = c; c = scan_getc(iop); nchars++; len--; } else if (c=='+') { len--; c = scan_getc(iop); nchars++; } cpos = 0; for ( ; --len>=0; *np++ = c, c = scan_getc(iop), nchars++) { cpos++; if (c == '0' && cpos == 1 && type == 'i') base = 8; if ((c == 'x' || c == 'X') && (type == 'i' || type == 'x') && cpos == 2 && lcval == 0) { base = 16; continue; } if (isdigit(c) || (base==16 && (('a'<=c && c<='f') || ('A'<=c && c<='F')))) { ndigit++; if (base==8) lcval <<=3; else if (base==10) lcval = ((lcval<<2) + lcval)<<1; else lcval <<= 4; c1 = c; if (isdigit(c)) c -= '0'; else if ('a'<=c && c<='f') c -= 'a'-10; else c -= 'A'-10; lcval += c; c = c1; continue; } else if (c=='.') { if (base!=10 || scale==INT) break; ndigit++; continue; } else if ((c=='e'||c=='E') && expseen==0) { if (base!=10 || scale==INT || ndigit==0) break; expseen++; *np++ = c; c = scan_getc(iop); nchars++; if (c!='+'&&c!='-'&&('0'>c||c>'9')) break; } else break; } if (negflg) lcval = -lcval; if (c != EOF) { scan_ungetc(c, iop); *eofptr = 0; } else *eofptr = 1; nchars--; if (ptr==NULL || np==numbuf || (negflg && np==numbuf+1) ) /* gene dykes*/ return(0); *np++ = 0; switch((scale<<4) | size) { case (FLOAT<<4) | SHORT: case (FLOAT<<4) | REGULAR: **(float **)ptr = atof(numbuf); break; case (FLOAT<<4) | LONG: **(double **)ptr = atof(numbuf); break; case (FLOAT<<4) | LONGDOUBLE: **(long double **)ptr = _atold(numbuf); break; case (INT<<4) | SHORT: **(short **)ptr = (short)lcval; break; case (INT<<4) | REGULAR: **(int **)ptr = (int)lcval; break; case (INT<<4) | LONG: case (INT<<4) | LONGDOUBLE: **(long **)ptr = lcval; break; } return(1); } static int _instr(char *ptr, int type, int len, FILE *iop, int (*scan_getc)(FILE *), int (*scan_ungetc)(int, FILE *), int *eofptr) { register ch; register char *optr; int ignstp; *eofptr = 0; optr = ptr; if (type=='c' && len==30000) len = 1; ignstp = 0; if (type=='s') ignstp = SPC; while ((nchars++, ch = scan_getc(iop)) != EOF && _sctab[ch] & ignstp) ; ignstp = SPC; if (type=='c') ignstp = 0; else if (type=='[') ignstp = STP; while (ch!=EOF && (_sctab[ch]&ignstp)==0) { if (ptr) *ptr++ = ch; if (--len <= 0) break; ch = scan_getc(iop); nchars++; } if (ch != EOF) { if (len > 0) { scan_ungetc(ch, iop); nchars--; } *eofptr = 0; } else { nchars--; *eofptr = 1; } if (ptr && ptr!=optr) { if (type!='c') *ptr++ = '\0'; return(1); } return(0); } static const char * _getccl(const unsigned char *s) { register c, t; t = 0; if (*s == '^') { t++; s++; } for (c = 0; c < (sizeof _sctab / sizeof _sctab[0]); c++) if (t) _sctab[c] &= ~STP; else _sctab[c] |= STP; if ((c = *s) == ']' || c == '-') { /* first char is special */ if (t) _sctab[c] |= STP; else _sctab[c] &= ~STP; s++; } while ((c = *s++) != ']') { if (c==0) return((const char *)--s); else if (c == '-' && *s != ']' && s[-2] < *s) { for (c = s[-2] + 1; c < *s; c++) if (t) _sctab[c] |= STP; else _sctab[c] &= ~STP; } else if (t) _sctab[c] |= STP; else _sctab[c] &= ~STP; } return((const char *)s); } ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- .---- Fred Smith / Office: fred AT computrition DOT com ( /__ ,__. __ __ / __ : / 508-663-2524 / / / /__) / / /__) .+' Home: fredex AT fcshome DOT stoneham DOT ma DOT us / / (__ (___ (__(_ (___ / :__ 617-438-5471 -------------------------------- Jude 1:24,25 ---------------------------------