📄 slstdio.c
字号:
/* file stdio intrinsics for S-Lang *//* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"#if defined(__unix__) || (defined (__os2__) && defined (__EMX__))# include <sys/types.h>#endif#ifdef HAVE_FCNTL_H# include <fcntl.h>#endif#ifdef HAVE_SYS_FCNTL_H# include <sys/fcntl.h>#endif#ifdef __unix__# include <sys/file.h>#endif#if defined(__BORLANDC__)# include <io.h># include <dir.h>#endif#if defined(__DECC) && defined(VMS)# include <unixio.h># include <unixlib.h>#endif#ifdef VMS# include <stat.h>#else# include <sys/stat.h>#endif#include <errno.h>#include <ctype.h>/* #define SL_APP_WANTS_FOREACH */#include "slang.h"#include "_slang.h"typedef struct{ FILE *fp; /* kind of obvious */ char *file; /* file name associated with pointer */ unsigned int flags; /* modes, etc... */#define SL_READ 0x0001#define SL_WRITE 0x0002#define SL_BINARY 0x0004#define SL_FDOPEN 0x2000#define SL_PIPE 0x4000#define SL_INUSE 0x8000}SL_File_Table_Type;static SL_File_Table_Type *SL_File_Table;static SL_File_Table_Type *get_free_file_table_entry (void){ SL_File_Table_Type *t = SL_File_Table, *tmax; tmax = t + SL_MAX_FILES; while (t < tmax) { if (t->flags == 0) { memset ((char *) t, 0, sizeof (SL_File_Table_Type)); return t; } t++; } return NULL;}static unsigned int file_process_flags (char *mode){ char ch; unsigned int flags = 0; while (1) { ch = *mode++; switch (ch) { case 'r': flags |= SL_READ; break; case 'w': case 'a': case 'A': flags |= SL_WRITE; break; case '+': flags |= SL_WRITE | SL_READ; break; case 'b': flags |= SL_BINARY; break; case 0: return flags; default: SLang_verror (SL_INVALID_PARM, "File flag %c is not supported", ch); return 0; } }}static int open_file_type (char *file, int fd, char *mode, FILE *(*open_fun)(char *, char *), int (*close_fun)(FILE *), unsigned int xflags){ FILE *fp; SL_File_Table_Type *t; unsigned int flags; SLang_MMT_Type *mmt; fp = NULL; /* t = NULL; */ mmt = NULL; if ((NULL == (t = get_free_file_table_entry ())) || (0 == (flags = file_process_flags(mode)))) goto return_error; if (fd != -1) fp = fdopen (fd, mode); else fp = open_fun (file, mode); if (fp == NULL) { _SLerrno_errno = errno; goto return_error; } if (NULL == (mmt = SLang_create_mmt (SLANG_FILE_PTR_TYPE, (VOID_STAR) t))) goto return_error; t->fp = fp; t->flags = flags | xflags; fp = NULL; /* allow free_mmt to close fp */ if ((NULL != (t->file = SLang_create_slstring (file))) && (0 == SLang_push_mmt (mmt))) return 0; /* drop */ return_error: if (fp != NULL) (*close_fun) (fp); if (mmt != NULL) SLang_free_mmt (mmt); (void) SLang_push_null (); return -1;}/* Since some compilers do not have popen/pclose prototyped and in scope, * and pc compilers sometimes have silly prototypes involving PASCAL, etc. * use wrappers around the function to avoid compilation errors. */static FILE *fopen_fun (char *f, char *m){ return fopen (f, m);}static int fclose_fun (FILE *fp){ return fclose (fp);}static void stdio_fopen (char *file, char *mode){ (void) open_file_type (file, -1, mode, fopen_fun, fclose_fun, 0);}int _SLstdio_fdopen (char *file, int fd, char *mode){ if (fd == -1) { _SLerrno_errno = EBADF; (void) SLang_push_null (); return -1; } return open_file_type (file, fd, mode, NULL, fclose_fun, SL_FDOPEN);}#ifdef HAVE_POPENstatic int pclose_fun (FILE *fp){ return pclose (fp);}static FILE *popen_fun (char *file, char *mode){ return popen (file, mode);}static void stdio_popen (char *file, char *mode){ (void) open_file_type (file, -1, mode, popen_fun, pclose_fun, SL_PIPE);}#endif/* returns pointer to file entry if it is open and consistent with flags. Returns NULL otherwise */static SLang_MMT_Type *pop_fp (unsigned int flags, FILE **fp_ptr){ SL_File_Table_Type *t; SLang_MMT_Type *mmt; *fp_ptr = NULL; if (NULL == (mmt = SLang_pop_mmt (SLANG_FILE_PTR_TYPE))) return NULL; t = (SL_File_Table_Type *) SLang_object_from_mmt (mmt); if ((t->flags & flags) && (NULL != (*fp_ptr = t->fp))) return mmt; SLang_free_mmt (mmt); return NULL;}static FILE *check_fp (SL_File_Table_Type *t, unsigned flags){ if ((t != NULL) && (t->flags & flags)) return t->fp; return NULL;}char *SLang_get_name_from_fileptr (SLang_MMT_Type *mmt){ SL_File_Table_Type *ft; ft = (SL_File_Table_Type *) SLang_object_from_mmt (mmt); if (ft == NULL) return NULL; return ft->file;}int SLang_pop_fileptr (SLang_MMT_Type **mmt, FILE **fp){ if (NULL == (*mmt = pop_fp (0xFFFF, fp))) {#ifdef EBADF _SLerrno_errno = EBADF;#endif return -1; } return 0;}static int close_file_type (SL_File_Table_Type *t){ int ret = 0; FILE *fp; if (t == NULL) return -1; fp = t->fp; if (NULL == fp) ret = -1; else { if (0 == (t->flags & SL_PIPE)) { if (EOF == (ret = fclose (fp))) _SLerrno_errno = errno; }#ifdef HAVE_POPEN else { if (-1 == (ret = pclose (fp))) _SLerrno_errno = errno; }#endif } if (t->file != NULL) SLang_free_slstring (t->file); memset ((char *) t, 0, sizeof (SL_File_Table_Type)); return ret;}static int stdio_fclose (SL_File_Table_Type *t){ int ret; if (NULL == check_fp (t, 0xFFFF)) return -1; ret = close_file_type (t); t->flags = SL_INUSE; return ret;}static int read_one_line (FILE *fp, char **strp, unsigned int *lenp, int trim_trailing){ char buf[512]; char *str; unsigned int len; *strp = NULL; len = 0; str = NULL; while (NULL != fgets (buf, sizeof (buf), fp)) { unsigned int dlen; char *new_str; int done_flag; dlen = strlen (buf); /* Note: If the file contains embedded \0 characters, then this * fails to work properly since dlen will not be correct. */ done_flag = ((dlen + 1 < sizeof (buf)) || (buf[dlen - 1] == '\n')); if (done_flag && (str == NULL)) { /* Avoid the malloc */ str = buf; len = dlen; break; } if (NULL == (new_str = SLrealloc (str, len + dlen + 1))) { SLfree (str); return -1; } str = new_str; strcpy (str + len, buf); len += dlen; if (done_flag) break; } if (str == NULL) return 0; if (trim_trailing) { unsigned int len1 = len; while (len1) { len1--; if (0 == isspace(str[len1])) { len1++; break; } } len = len1; } *strp = SLang_create_nslstring (str, len); if (str != buf) SLfree (str); if (*strp == NULL) return -1; *lenp = len; return 1;}/* returns number of characters read and pushes the string to the stack. If it fails, it returns -1 */static int stdio_fgets (SLang_Ref_Type *ref, SL_File_Table_Type *t){ char *s; unsigned int len; FILE *fp; int status; if (NULL == (fp = check_fp (t, SL_READ))) return -1; status = read_one_line (fp, &s, &len, 0); if (status <= 0) return -1; status = SLang_assign_to_ref (ref, SLANG_STRING_TYPE, (VOID_STAR)&s); SLang_free_slstring (s); if (status == -1) return -1; return (int) len;}static void stdio_fgetslines_internal (FILE *fp, unsigned int n){ unsigned int num_lines, max_num_lines; char **list; SLang_Array_Type *at; int inum_lines; if (n > 1024) max_num_lines = 1024; else { max_num_lines = n; if (max_num_lines == 0) max_num_lines++; } list = (char **) SLmalloc (sizeof (char *) * max_num_lines); if (list == NULL) return; num_lines = 0; while (num_lines < n) { int status; char *line; unsigned int len; status = read_one_line (fp, &line, &len, 0); if (status == -1) goto return_error; if (status == 0) break; if (max_num_lines == num_lines) { char **new_list; if (max_num_lines + 4096 > n) max_num_lines = n; else max_num_lines += 4096; new_list = (char **) SLrealloc ((char *)list, sizeof (char *) * max_num_lines); if (new_list == NULL) { SLang_free_slstring (line); goto return_error; } list = new_list; } list[num_lines] = line; num_lines++; } if (num_lines != max_num_lines) { char **new_list; new_list = (char **)SLrealloc ((char *)list, sizeof (char *) * (num_lines + 1)); if (new_list == NULL) goto return_error; list = new_list; } inum_lines = (int) num_lines; if (NULL == (at = SLang_create_array (SLANG_STRING_TYPE, 0, (VOID_STAR) list, &inum_lines, 1))) goto return_error; if (-1 == SLang_push_array (at, 1)) SLang_push_null (); return; return_error: while (num_lines > 0) { num_lines--; SLfree (list[num_lines]); } SLfree ((char *)list); SLang_push_null ();}static void stdio_fgetslines (void){ unsigned int n; FILE *fp; SLang_MMT_Type *mmt; n = (unsigned int)-1; if (SLang_Num_Function_Args == 2) { if (-1 == SLang_pop_uinteger (&n)) return; } if (NULL == (mmt = pop_fp (SL_READ, &fp))) { SLang_push_null (); return; } stdio_fgetslines_internal (fp, n); SLang_free_mmt (mmt);}static int stdio_fputs (char *s, SL_File_Table_Type *t){ FILE *fp; if (NULL == (fp = check_fp (t, SL_WRITE))) return -1; if (EOF == fputs(s, fp)) return -1; return (int) strlen (s);}static int stdio_fflush (SL_File_Table_Type *t){ FILE *fp; if (NULL == (fp = check_fp (t, SL_WRITE))) return -1; if (EOF == fflush (fp)) { _SLerrno_errno = errno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -