📄 routines.c
字号:
/** $Id: routines.c,v 1.21 2003/10/31 04:15:35 darren Exp $** Copyright (c) 2002-2003, Darren Hiebert** This source code is released for free distribution under the terms of the* GNU General Public License.** This module contains a lose assortment of shared functions.*//** INCLUDE FILES*/#include "general.h" /* must always come first */#ifdef HAVE_STDLIB_H# include <stdlib.h> /* to declare malloc (), realloc () */#endif#include <ctype.h>#include <string.h>#include <stdarg.h>#include <errno.h>#include <stdio.h> /* to declare tempnam(), and SEEK_SET (hopefully) */#ifdef HAVE_FCNTL_H# include <fcntl.h> /* to declar O_RDWR, O_CREAT, O_EXCL */#endif#ifdef HAVE_UNISTD_H# include <unistd.h> /* to declare mkstemp () */#endif/* To declare "struct stat" and stat (). */#if defined (HAVE_SYS_TYPES_H)# include <sys/types.h>#else# if defined (HAVE_TYPES_H)# include <types.h># endif#endif#ifdef HAVE_SYS_STAT_H# include <sys/stat.h>#else# ifdef HAVE_STAT_H# include <stat.h># endif#endif#ifdef HAVE_DOS_H# include <dos.h> /* to declare MAXPATH */#endif#ifdef HAVE_DIRECT_H# include <direct.h> /* to _getcwd */#endif#ifdef HAVE_DIR_H# include <dir.h> /* to declare findfirst() and findnext() */#endif#ifdef HAVE_IO_H# include <io.h> /* to declare open() */#endif#include "debug.h"#include "routines.h"#ifdef TRAP_MEMORY_CALLS# include "safe_malloc.h"#endif/** MACROS*/#ifndef TMPDIR# define TMPDIR "/tmp"#endif/* File type tests. */#ifndef S_ISREG# if defined (S_IFREG) && ! defined (AMIGA)# define S_ISREG(mode) ((mode) & S_IFREG)# else# define S_ISREG(mode) TRUE /* assume regular file */# endif#endif#ifndef S_ISLNK# ifdef S_IFLNK# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)# else# define S_ISLNK(mode) FALSE /* assume no soft links */# endif#endif#ifndef S_ISDIR# ifdef S_IFDIR# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)# else# define S_ISDIR(mode) FALSE /* assume no soft links */# endif#endif#ifndef S_IFMT# define S_IFMT 0#endif#ifndef S_IXUSR# define S_IXUSR 0#endif#ifndef S_IXGRP# define S_IXGRP 0#endif#ifndef S_IXOTH# define S_IXOTH 0#endif#ifndef S_IRUSR# define S_IRUSR 0400#endif#ifndef S_IWUSR# define S_IWUSR 0200#endif#ifndef S_ISUID# define S_ISUID 0#endif/* Hack for rediculous practice of Microsoft Visual C++. */#if defined (WIN32)# if defined (_MSC_VER)# define stat _stat# define getcwd _getcwd# define currentdrive() (_getdrive() + 'A' - 1)# define PATH_MAX _MAX_PATH# elif defined (__BORLANDC__)# define PATH_MAX MAXPATH# define currentdrive() (getdisk() + 'A')# elif defined (DJGPP)# define currentdrive() (getdisk() + 'A')# else# define currentdrive() 'C'# endif#endif#ifndef PATH_MAX# define PATH_MAX 256#endif/* * Miscellaneous macros */#define selected(var,feature) (((int)(var) & (int)(feature)) == (int)feature)/** DATA DEFINITIONS*/#if defined (MSDOS_STYLE_PATH)const char *const PathDelimiters = ":/\\";#elif defined (VMS)const char *const PathDelimiters = ":]>";#endifchar *CurrentDirectory;static const char *ExecutableProgram;static const char *ExecutableName;/** FUNCTION PROTOTYPES*/#ifdef NEED_PROTO_STATextern int stat (const char *, struct stat *);#endif#ifdef NEED_PROTO_LSTATextern int lstat (const char *, struct stat *);#endif#if defined (MSDOS) || defined (WIN32) || defined (VMS) || defined (__EMX__) || defined (AMIGA)# define lstat(fn,buf) stat(fn,buf)#endif/** FUNCTION DEFINITIONS*/extern void freeRoutineResources (void){ if (CurrentDirectory != NULL) eFree (CurrentDirectory);}extern void setExecutableName (const char *const path){ ExecutableProgram = path; ExecutableName = baseFilename (path);#ifdef VAXC{ /* remove filetype from executable name */ char *p = strrchr (ExecutableName, '.'); if (p != NULL) *p = '\0';}#endif}extern const char *getExecutableName (void){ return ExecutableName;}extern void error (const errorSelection selection, const char *const format, ...){ va_list ap; va_start (ap, format); fprintf (errout, "%s: %s", getExecutableName (), selected (selection, WARNING) ? "Warning: " : ""); vfprintf (errout, format, ap); if (selected (selection, PERROR))#ifdef HAVE_STRERROR fprintf (errout, " : %s", strerror (errno));#else perror (" ");#endif fputs ("\n", errout); va_end (ap); if (selected (selection, FATAL)) exit (1);}/* * Memory allocation functions */extern void *eMalloc (const size_t size){ void *buffer = malloc (size); if (buffer == NULL) error (FATAL, "out of memory"); return buffer;}extern void *eCalloc (const size_t count, const size_t size){ void *buffer = calloc (count, size); if (buffer == NULL) error (FATAL, "out of memory"); return buffer;}extern void *eRealloc (void *const ptr, const size_t size){ void *buffer; if (ptr == NULL) buffer = eMalloc (size); else { buffer = realloc (ptr, size); if (buffer == NULL) error (FATAL, "out of memory"); } return buffer;}extern void eFree (void *const ptr){ Assert (ptr != NULL); free (ptr);}/* * String manipulation functions *//* * Compare two strings, ignoring case. * Return 0 for match, < 0 for smaller, > 0 for bigger * Make sure case is folded to uppercase in comparison (like for 'sort -f') * This makes a difference when one of the chars lies between upper and lower * ie. one of the chars [ \ ] ^ _ ` for ascii. (The '_' in particular !) */extern int struppercmp (const char *s1, const char *s2){ int result; do { result = toupper ((int) *s1) - toupper ((int) *s2); } while (result == 0 && *s1++ != '\0' && *s2++ != '\0'); return result;}extern int strnuppercmp (const char *s1, const char *s2, size_t n){ int result; do { result = toupper ((int) *s1) - toupper ((int) *s2); } while (result == 0 && --n > 0 && *s1++ != '\0' && *s2++ != '\0'); return result;}#ifndef HAVE_STRSTRextern char* strstr (const char *str, const char *substr){ const size_t length = strlen (substr); const char *match = NULL; const char *p; for (p = str ; *p != '\0' && match == NULL ; ++p) if (strncmp (p, substr, length) == 0) match = p; return (char*) match;}#endifextern char* eStrdup (const char* str){ char* result = xMalloc (strlen (str) + 1, char); strcpy (result, str); return result;}extern void toLowerString (char* str){ while (*str != '\0') { *str = tolower ((int) *str); ++str; }}extern void toUpperString (char* str){ while (*str != '\0') { *str = toupper ((int) *str); ++str; }}/* Newly allocated string containing lower case conversion of a string. */extern char* newLowerString (const char* str){ char* const result = xMalloc (strlen (str) + 1, char); int i = 0; do result [i] = tolower ((int) str [i]); while (str [i++] != '\0'); return result;}/* Newly allocated string containing upper case conversion of a string. */extern char* newUpperString (const char* str){ char* const result = xMalloc (strlen (str) + 1, char); int i = 0; do result [i] = toupper ((int) str [i]); while (str [i++] != '\0'); return result;}/* * File system functions */extern void setCurrentDirectory (void){#ifndef AMIGA char* buf;#endif if (CurrentDirectory == NULL) CurrentDirectory = xMalloc ((size_t) (PATH_MAX + 1), char);#ifdef AMIGA strcpy (CurrentDirectory, ".");#else buf = getcwd (CurrentDirectory, PATH_MAX); if (buf == NULL) perror ("");#endif if (CurrentDirectory [strlen (CurrentDirectory) - (size_t) 1] != PATH_SEPARATOR) { sprintf (CurrentDirectory + strlen (CurrentDirectory), "%c", OUTPUT_PATH_SEPARATOR); }}#ifdef AMIGAstatic boolean isAmigaDirectory (const char *const name){ boolean result = FALSE; struct FileInfoBlock *const fib = xMalloc (1, struct FileInfoBlock); if (fib != NULL) { const BPTR flock = Lock ((UBYTE *) name, (long) ACCESS_READ); if (flock != (BPTR) NULL) { if (Examine (flock, fib)) result = ((fib->fib_DirEntryType >= 0) ? TRUE : FALSE); UnLock (flock); } eFree (fib); } return result;}#endif/* For caching of stat() calls */extern fileStatus *eStat (const char *const fileName){ struct stat status; static fileStatus file; if (file.name == NULL || strcmp (fileName, file.name) != 0) { if (file.name != NULL) eFree (file.name); file.name = eStrdup (fileName); if (lstat (file.name, &status) != 0) file.exists = FALSE; else { file.isSymbolicLink = (boolean) S_ISLNK (status.st_mode); if (file.isSymbolicLink && stat (file.name, &status) != 0) file.exists = FALSE; else { file.exists = TRUE;#ifdef AMIGA file.isDirectory = isAmigaDirectory (file.name);#else file.isDirectory = (boolean) S_ISDIR (status.st_mode);#endif file.isNormalFile = (boolean) (S_ISREG (status.st_mode));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -