ctags/mac.c

274 lines
4.9 KiB
C

/*
* $Id$
*
* Copyright (c) 2001, Maarten L. Hekkelman
*
* Author: Maarten L. Hekkelman <maarten@hekkelman.com>
* http://www.hekkelman.com
*
* This source code is released for free distribution under the terms of the
* GNU General Public License. It is provided on an as-is basis and no
* responsibility is accepted for its failure to perform as expected.
*
* This module contains support functions for Exuberant Ctags on Macintosh.
*/
/*
* INCLUDE FILES
*/
#include "general.h"
#include <Files.h>
#include <TextUtils.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/*
* FUNCTION DEFINITIONS
*/
static int get_path(const char* in_unix_path, unsigned char* out_mac_path)
{
int l = strlen(in_unix_path);
int result = 0;
if (l > 254)
result = -1;
else
{
const char* s = in_unix_path;
char *d = (char*)out_mac_path + 1;
if (*s != '/')
*d++ = ':';
else
++s;
while (*s)
{
if (s[0] == '.' && s[1] == '.' && s[2] == '/')
{
s += 3;
*d++ = ':';
}
else if (s[0] == '.' && s[1] == '/')
s += 2;
else if (s[0] == '/')
{
*d++ = ':';
++s;
while (*s == '/')
++s;
}
else
*d++ = *s++;
}
out_mac_path[0] = (d - (char*)out_mac_path) - 1;
}
return result;
}
DIR *opendir(const char *dirname)
{
DIR* dirp = (DIR*)calloc(1, sizeof(DIR));
if (dirp != NULL)
{
OSErr err;
Str255 s;
CInfoPBRec pb = { 0 };
if (strcmp(dirname, "."))
{
get_path(dirname, s);
pb.hFileInfo.ioNamePtr = s;
}
else
pb.hFileInfo.ioNamePtr = NULL;
err = PBGetCatInfoSync(&pb);
if (err != noErr || (pb.hFileInfo.ioFlAttrib & ioDirMask) == 0)
{
free(dirp);
dirp = NULL;
}
else
{
dirp->file.vRefNum = pb.hFileInfo.ioVRefNum;
dirp->file.parID = pb.hFileInfo.ioDirID;
dirp->file.name[0] = '\0';
dirp->index = 1;
}
}
return dirp;
}
struct dirent *readdir(DIR *dirp)
{
if (dirp)
{
CInfoPBRec pb = { 0 };
pb.hFileInfo.ioVRefNum = dirp->file.vRefNum;
pb.hFileInfo.ioDirID = dirp->file.parID;
pb.hFileInfo.ioFDirIndex = dirp->index++;
pb.hFileInfo.ioNamePtr = dirp->file.name;
if (PBGetCatInfoSync(&pb) != noErr)
return NULL;
memcpy(dirp->ent.d_name, dirp->file.name + 1, dirp->file.name[0]);
dirp->ent.d_name[dirp->file.name[0]] = 0;
return &dirp->ent;
}
return NULL;
}
int closedir(DIR *dirp)
{
if (dirp)
free(dirp);
return 0;
}
void rewinddir(DIR *dirp)
{
if (dirp)
dirp->index = 1;
}
int mstat(const char* file, struct stat* st)
{
CInfoPBRec pb;
unsigned char path[256];
int result = 0;
memset(&pb, 0, sizeof(CInfoPBRec));
if (strcmp(file, ".") == 0)
{
memset(st, 0, sizeof(struct stat));
st->st_mode = S_IFDIR;
st->st_ino = -1;
}
else
{
result = get_path(file, path);
if (result == 0)
{
pb.hFileInfo.ioNamePtr = path;
if (PBGetCatInfoSync(&pb) != noErr)
result = -1;
else
{
memset(st, 0, sizeof(struct stat));
if (pb.hFileInfo.ioFlAttrib & ioDirMask)
st->st_mode = S_IFDIR;
else
st->st_mode = S_IFREG;
st->st_ino = pb.hFileInfo.ioFlStBlk;
st->st_dev = pb.hFileInfo.ioVRefNum;
st->st_nlink = 1;
st->st_size = pb.hFileInfo.ioFlLgLen;
st->st_atime = pb.hFileInfo.ioFlMdDat;
st->st_mtime = pb.hFileInfo.ioFlMdDat;
st->st_ctime = pb.hFileInfo.ioFlCrDat;
}
}
}
return result;
}
#undef fopen
FILE* mfopen(const char* file, const char* mode)
{
unsigned char path[256];
if (get_path(file, path) == 0)
{
int l = path[0];
memmove(path, path + 1, l);
path[l] = 0;
return fopen((char*)path, mode);
}
else
return NULL;
}
char* getcwd(char* out_path, int out_path_len)
{
OSErr err = noErr;
CInfoPBRec pb;
FSSpec cwd;
if (out_path == NULL)
{
if (out_path_len < PATH_MAX)
out_path_len = PATH_MAX;
out_path = (char*)malloc(out_path_len);
}
err = FSMakeFSSpec(0, 0, "\p:", &cwd);
if (cwd.parID == fsRtParID)
{
*out_path = '/';
memcpy(out_path + 1, cwd.name + 1, cwd.name[0]);
out_path[1 + cwd.name[0]] = 0;
}
else
{
/* The object isn't a volume */
/* Is the object a file or a directory? */
char t[PATH_MAX];
char* s;
s = t + PATH_MAX - cwd.name[0] - 1;
memcpy(s, cwd.name + 1, cwd.name[0]);
s[cwd.name[0]] = 0;
/* Get the ancestor directory names */
pb.dirInfo.ioNamePtr = cwd.name;
pb.dirInfo.ioVRefNum = cwd.vRefNum;
pb.dirInfo.ioDrParID = cwd.parID;
do /* loop until we have an error or find the root directory */
{
pb.dirInfo.ioFDirIndex = -1;
pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID;
err = PBGetCatInfoSync(&pb);
if ( err == noErr )
{
*--s = '/';
s -= cwd.name[0];
memcpy(s, cwd.name + 1, cwd.name[0]);
}
}
while (err == noErr && pb.dirInfo.ioDrDirID != fsRtDirID && s > t + 1);
if (s > t + 1)
{
*--s = '/';
strcpy(out_path, s);
}
else
strcpy(out_path, ".");
}
return out_path;
}
/* vi:set tabstop=4 shiftwidth=4: */