📄 file.c
字号:
if (!fiop->writing || fiop->action == 'r') return 0; return fflush(fiop->fp);}#if !defined(_WIN32)intflushall(void){ FILEIO *fiop; int i; int err; err = 0; for (i = 3; i < idnum; i++) { fiop = &files[ioindex[i]]; if (fiop->writing && fiop->action != 'r') err |= fflush(fiop->fp); } return err;}#endif /* Windoz free systems *//* * Read the next line, string or word from an opened file. * Returns a pointer to an allocated string holding a null-terminated * or newline terminated string. Where reading stops is controlled by * flags: * * bit 0: at newline * bit 1: at null character * bit 2: at white space (also skips leading white space) * * If neither '\n' nor '\0' is encountered reading continues until EOF. * If bit 3 is set the stop character is removed. * * given: * id file to read from * flags read flags (see above) * retstr returned pointer to string */intreadid(FILEID id, int flags, STRING **retstr){ FILEIO *fiop; /* file structure */ FILE *fp; char *str; /* current string */ unsigned long n; /* current number characters read into buf */ unsigned long totlen; /* total length of string copied from buf */ char buf[READSIZE]; /* temporary buffer */ char *b; int c; BOOL nlstop, nullstop, wsstop, rmstop, done; FILEPOS fpos; STRING *newstr; totlen = 0; str = NULL; fiop = findid(id, FALSE); if (fiop == NULL) return 1; nlstop = (flags & 1); nullstop = (flags & 2); wsstop = (flags & 4); rmstop = (flags & 8); fp = fiop->fp; if (fiop->action == 'w') { f_tell(fp, &fpos); fflush(fp); if (f_seek_set(fp, &fpos) < 0) return 3; } fiop->action = 'r'; if (wsstop) { while (isspace(c = fgetc(fp))); ungetc(c, fp); } for (;;) { b = buf; n = 0; do { c = fgetc(fp); if (c == EOF) break; n++; if (nlstop && c == '\n') break; if (nullstop && c == '\0') break; if (wsstop && isspace(c)) break; *b++ = c; } while (n < READSIZE); done = ((nlstop && c == '\n') || (nullstop && c == '\0') || (wsstop && isspace(c)) || c == EOF); if (done && rmstop && c != EOF) n--; if (totlen) str = (char *)realloc(str, totlen + n + 1); else str = (char *)malloc(n + 1); if (str == NULL) { math_error("Out of memory for readid"); /*NOTREACHED*/ } if (n > 0) memcpy(&str[totlen], buf, n); totlen += n; if (done) break; } if (totlen == 0 && c == EOF) { free(str); return EOF; } if ((nlstop && c == '\n') && !rmstop) str[totlen - 1] = '\n'; if ((nullstop && c == '\0') && !rmstop) str[totlen - 1] = '\0'; str[totlen] = '\0'; newstr = stralloc(); newstr->s_len = totlen; newstr->s_str = str; *retstr = newstr; return 0;}/* * Return the next character from an opened file. * Returns EOF if there was an error or end of file. */intgetcharid(FILEID id){ FILEIO *fiop; FILEPOS fpos; fiop = findid(id, FALSE); if (fiop == NULL) return -2; if (fiop->action == 'w') { f_tell(fiop->fp, &fpos); fflush(fiop->fp); if (f_seek_set(fiop->fp, &fpos) < 0) return -3; } fiop->action = 'r'; return fgetc(fiop->fp);}/* * Print out the name of an opened file. * If the file has been closed, a null name is printed. * If flags contain PRINT_UNAMBIG then extra information is printed * identifying the output as a file and some data about it. */intprintid(FILEID id, int flags){ FILEIO *fiop; /* file structure */ FILE *fp; ZVALUE pos; /* file position */ /* * filewall - file is closed */ fiop = findid(id, -1); if (fiop == NULL) { if (flags & PRINT_UNAMBIG) math_fmt("FILE %d closed", id); else math_str("\"\""); return 1; } /* * print quoted filename and mode */ if ((flags & PRINT_UNAMBIG) == 0) { math_chr('"'); math_str(fiop->name); math_chr('"'); return 0; } math_fmt("FILE %d \"%s\" (%s", id, fiop->name, fiop->mode); /* * print file position */ fp = fiop->fp; if (get_open_pos(fp, &pos) < 0) { if (fileno(fp) > 2) math_str("Error while determining file position!"); math_chr(')'); return 0; } math_str(", pos "); zprintval(pos, 0, 0); zfree(pos); /* * report special status */ if (ferror(fp)) math_str(", error"); if (feof(fp)) math_str(", eof"); math_chr(')'); printf(" fileno: %d ", fileno(fp)); return 0;}/* * Print a formatted string similar to printf. Various formats of output * are possible, depending on the format string AND the actual types of the * values. Mismatches do not cause errors, instead something reasonable is * printed instead. The output goes to the file with the specified id. * * given: * id file id to print to * count print count * fmt standard format string * vals table of values to print */intidprintf(FILEID id, char *fmt, int count, VALUE **vals){ FILEIO *fiop; VALUE *vp; char *str; int ch; size_t len; int oldmode, newmode; long olddigits, newdigits; long width, precision; BOOL didneg, didprecision; FILEPOS fpos; BOOL printstring; BOOL printchar; fiop = findid(id, TRUE); if (fiop == NULL) return 1; if (fiop->action == 'r') { f_tell(fiop->fp, &fpos); if (f_seek_set(fiop->fp, &fpos) < 0) return 3; } fiop->action = 'w'; printstring = FALSE; printchar = FALSE; math_setfp(fiop->fp); while ((ch = *fmt++) != '\0') { if (ch != '%') { math_chr(ch); continue; } /* * Here to handle formats. */ didneg = FALSE; didprecision = FALSE; width = 0; precision = 0; ch = *fmt++; if (ch == '-') { didneg = TRUE; ch = *fmt++; } while ((ch >= '0') && (ch <= '9')) { width = width * 10 + (ch - '0'); ch = *fmt++; } if (ch == '.') { didprecision = TRUE; ch = *fmt++; while ((ch >= '0') && (ch <= '9')) { precision = precision * 10 + (ch - '0'); ch = *fmt++; } } if (ch == 'l') ch = *fmt++; oldmode = conf->outmode; newmode = oldmode; olddigits = conf->outdigits; newdigits = olddigits; if (didprecision) newdigits = precision; switch (ch) { case 's': printstring = TRUE; case 'c': printchar = TRUE; case 'd': break; case 'f': newmode = MODE_REAL; break; case 'e': newmode = MODE_EXP; break; case 'r': newmode = MODE_FRAC; break; case 'o': newmode = MODE_OCTAL; break; case 'x': newmode = MODE_HEX; break; case 'b': newmode = MODE_BINARY; break; case 0: math_setfp(stdout); return 0; default: math_chr(ch); continue; } if (--count < 0) { while (width-- > 0) math_chr(' '); continue; } vp = *vals++; math_setdigits(newdigits); math_setmode(newmode); /* * If there is no width specification, or if the type of * value requires multiple lines, then just output the * value directly. */ if ((width == 0) || (vp->v_type == V_MAT) || (vp->v_type == V_LIST)) { switch(vp->v_type) { case V_OCTET: if (printstring) math_str((char *)vp->v_octet); else if (printchar) math_chr(*vp->v_octet); else printvalue(vp, PRINT_NORMAL); break; case V_BLOCK: if (printstring) math_str((char *) vp->v_block->data); else if (printchar) math_chr(*vp->v_block->data); else printvalue(vp, PRINT_NORMAL); break; case V_NBLOCK: if (printstring) { if (vp->v_nblock->blk->data != NULL) math_str((char *) vp->v_nblock ->blk->data); } else if (printchar) { if (vp->v_nblock->blk->data != NULL) math_chr(*vp->v_nblock-> blk->data); } else { printvalue(vp, PRINT_NORMAL); } break; default: printvalue(vp, PRINT_NORMAL); } math_setmode(oldmode); math_setdigits(olddigits); continue; } /* * There is a field width. Collect the output in a string, * print it padded appropriately with spaces, and free it. * However, if the output contains a newline, then ignore * the field width. */ math_divertio(); switch(vp->v_type) { case V_OCTET: if (printstring) math_str((char *)vp->v_octet); else if (printchar) math_chr(*vp->v_octet); else printvalue(vp, PRINT_NORMAL); break; case V_BLOCK: if (printstring) math_str((char *)vp->v_block->data); else if (printchar) math_chr(*vp->v_block->data); else printvalue(vp, PRINT_NORMAL); break; case V_NBLOCK: if (printstring) { if (vp->v_nblock->blk->data != NULL) math_str((char *) vp->v_nblock->blk->data); } else if (printchar) { if (vp->v_nblock->blk->data != NULL) math_chr(*vp->v_nblock->blk->data); } else printvalue(vp, PRINT_NORMAL); break; default: printvalue(vp, PRINT_NORMAL); } str = math_getdivertedio(); if (strchr(str, '\n')) width = 0; len = strlen(str); while (!didneg && ((size_t)width > len)) { width--; math_chr(' '); } math_str(str); free(str); while (didneg && ((size_t)width > len)) { width--; math_chr(' '); } math_setmode(oldmode); math_setdigits(olddigits); } math_setfp(stdout); return 0;}/* * Write a character to a file. * * given: * id file id to print to * ch character to write */intidfputc(FILEID id, int ch){ FILEIO *fiop; FILEPOS fpos; /* get the file info pointer */ fiop = findid(id, TRUE); if (fiop == NULL) return 1; if (fiop->action == 'r') { f_tell(fiop->fp, &fpos); if (f_seek_set(fiop->fp, &fpos) < 0) return 2; } fiop->action = 'w'; /* set output to file */ math_setfp(fiop->fp); /* write char */ math_chr(ch); /* restore output to stdout */ math_setfp(stdout); return 0;}/* * Unget a character read from a file. * * given: * id file id to print to * ch character to write */intidungetc(FILEID id, int ch){ FILEIO *fiop; fiop = findid(id, FALSE); if (fiop == NULL) return -2; if (fiop->action != 'r') return -2; return ungetc(ch, fiop->fp);}/* * Write a string to a file. * * given: * id file id to print to * str string to write */intidfputs(FILEID id, STRING *str){ FILEIO *fiop; FILEPOS fpos; FILE *fp; char *c; long len; /* get the file info pointer */ fiop = findid(id, TRUE); if (fiop == NULL) return 1; if (fiop->action == 'r') { f_tell(fiop->fp, &fpos); if (f_seek_set(fiop->fp, &fpos) < 0) return 2; } fiop->action = 'w'; fp = fiop->fp; len = str->s_len; c = str->s_str; while (len-- > 0) fputc(*c++, fp); return 0;}/* * Same as idfputs but writes a terminating null character * * given: * id file id to print to * str string to write */intidfputstr(FILEID id, char *str){ FILEIO *fiop; FILEPOS fpos; /* get the file info pointer */ fiop = findid(id, TRUE); if (fiop == NULL) return 1; if (fiop->action == 'r') { f_tell(fiop->fp, &fpos); if (f_seek_set(fiop->fp, &fpos) < 0) return 2; } fiop->action = 'w'; /* set output to file */ math_setfp(fiop->fp); /* write the string */ math_str(str); math_chr('\0'); /* restore output to stdout */ math_setfp(stdout); return 0;}intrewindid(FILEID id){ FILEIO *fiop; fiop = findid(id, -1); if (fiop == NULL) return 1; rewind(fiop->fp); fiop->action = 0; return 0;}voidrewindall(void){ FILEIO *fiop; int i; for (i = 3; i < idnum; i++) { fiop = &files[ioindex[i]]; if (fiop != NULL) { (void) rewind(fiop->fp); fiop->action = 0; } }}/* * filepos2z - convert a positive file position into a ZVALUE * * given: * pos file position * * returns: * file position as a ZVALUE * * NOTE: Does not support negative file positions. *//*ARGSUSED*/static ZVALUEfilepos2z(FILEPOS pos){ ZVALUE ret; /* ZVALUE file position to return */ /* * store FILEPOS in a ZVALUE as a positive value */ ret.len = FILEPOS_BITS/BASEB; ret.v = alloc(ret.len); zclearval(ret); SWAP_HALF_IN_FILEPOS(ret.v, (HALF *)&pos); ret.sign = 0; ztrim(&ret); /* * return our result */ return ret;}/* * z2filepos - convert a positive ZVALUE file position to a FILEPOS * * given: * zpos file position as a ZVALUE * * returns: * file position as a FILEPOS * * NOTE: Does not support negative file positions. */static FILEPOSz2filepos(ZVALUE zpos){#if FILEPOS_BITS > FULL_BITS FILEPOS tmp; /* temp file position as a FILEPOS */#endif FILEPOS ret; /* file position as a FILEPOS */#if FILEPOS_BITS < FULL_BITS long pos; /* zpos as a long */#else FULL pos; /* zpos as a FULL */#endif /* * firewall */ zpos.sign = 0; /* deal only with the absolue value */ /* * quick return if the position can fit into a long */#if FILEPOS_BITS == FULL_BITS /* ztofull puts the value into native byte order */ pos = ztofull(zpos); /* on some hosts, FILEPOS is not a scalar */ memset(&ret, 0, sizeof(FILEPOS)); memcpy((void *)&ret, (void *)&pos, sizeof(FILEPOS));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -