Commit 1d1208ac authored by John van Groningen's avatar John van Groningen
Browse files

cli for MacOSX with MACH_O, same as unix, except : and , are used

in paths and object files generated by the c compiler have different
names
parent 54844b4d
#define Clean(a)
typedef struct clean_string *CleanString;
/* a string in Clean is:
struct clean_string {
int clean_string_length;
char clean_string_characters[clean_string_length];
};
The string does not end with a '\0' !
*/
/* CleanStringLength(clean_string) returns length of the clean_string in characters */
#define CleanStringLength(clean_string) (*(unsigned int *)(clean_string))
/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */
#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned int *)(clean_string)))
/* CleanStringSizeInts(string_length) return size of CleanString in integers */
#define CleanStringSizeInts(string_length) (1+(((unsigned int)(string_length)+3)>>2))
/* CleanStringVariable(clean_string,string_length) defines variable clean_string with length string_length,
before using the clean_string variable, cast to CleanString, except for the macros above */
#define CleanStringVariable(clean_string,string_length) unsigned int clean_string[CleanStringSizeInts(string_length)]
/* CleanStringSizeBytes(string_length) return size of CleanString in bytes */
#define CleanStringSizeBytes(string_length) (4+(((unsigned int)(string_length)+3) & -4))
// this is for Windows
definition module CoclSystemDependent
//1.3
from StdString import String
from StdFile import Files
//3.1
/*2.0
from StdFile import ::Files
0.2*/
// RWS split
// from deltaIOSystem import DeviceSystem
// from deltaEventIO import InitialIO, IOState
PathSeparator
:== ','
DirectorySeparator
:== ':'
SystemDependentDevices :: [a]
SystemDependentInitialIO :: [a]
ensureCleanSystemFilesExists :: !String !*Files -> (!Bool, !*Files)
set_compiler_id :: Int -> Int
compiler_loop :: ([{#Char}] *st -> *(Bool, *st)) *st -> (!Bool, !*st)
// this is for Unix
implementation module CoclSystemDependent
import StdEnv
import StdDebug
import ArgEnv
import ipc
from filesystem import ensureDirectoryExists
import code from "cDirectory_c.o"
import code from "ipc_c.o"
PathSeparator
:== ','
DirectorySeparator
:== ':'
SystemDependentDevices :: [a]
SystemDependentDevices
= []
SystemDependentInitialIO :: [a]
SystemDependentInitialIO
= []
set_compiler_id :: Int -> Int
set_compiler_id compiler_id = compiler_id
ensureCleanSystemFilesExists :: !String !*Files -> (!Bool, !*Files)
// returned bool: now there is such a subfolder
ensureCleanSystemFilesExists path env
= ensureDirectoryExists path env
compiler_loop :: ([{#Char}] *st -> *(Bool, *st)) *st -> (!Bool, !*st)
compiler_loop compile compile_state
| length commandArgs==3 && commandArgs!!0=="--pipe"
# commands_name= (commandArgs!!1);
# results_name= (commandArgs!!2);
= (True,compile_loop compile commands_name results_name compile_state)
# (r,compile_state)=compile commandArgs compile_state
= (r,compile_state)
where
commandArgs
= tl [arg \\ arg <-: getCommandLine]
// ... Unix
string_to_args string
= string_to_args 0;
where
l=size string;
string_to_args i
# end_spaces_i=skip_spaces i;
| end_spaces_i==l
= []
| string.[end_spaces_i]=='"'
# next_double_quote_i=skip_to_double_quote (end_spaces_i+1)
| next_double_quote_i>=l
= [string % (end_spaces_i,l-1)]
# arg=string % (end_spaces_i+1,next_double_quote_i-1);
= [arg : string_to_args (next_double_quote_i+1)];
# space_i=skip_to_space (end_spaces_i+1)
| space_i>=l
= [string % (end_spaces_i,l-1)]
# arg=string % (end_spaces_i,space_i-1);
= [arg : string_to_args (space_i+1)];
skip_spaces i
| i>=l
= l;
# c=string.[i];
| c==' ' || c=='\t'
= skip_spaces (i+1);
= i;
skip_to_space i
| i>=l
= l;
# c=string.[i];
| c==' ' || c=='\t'
= i;
= skip_to_space (i+1);
skip_to_double_quote i
| i>=l
= l;
# c=string.[i];
| c=='"'
= i;
= skip_to_double_quote (i+1);
compile_loop :: ([{#Char}] *st -> *(Bool, *st)) {#Char} {#Char} *st -> *st
compile_loop compile commands results compile_state
# r=open_pipes commands results;
| r<>0
= abort ("compile_loop\n");
= compile_files compile compile_state
compile_files :: ([{#Char}] *st -> *(Bool, *st)) *st -> *st
compile_files compile compile_state
# n = get_command_length;
| n==(-1)
= abort "compile_files 1";
# string=createArray n '\0';
# r=get_command string;
| r<>0
= abort ("compile_files 2 ");
# args=string_to_args (string % (0,size string-2))
= case args of
["cocl":cocl_args]
# (ok,compile_state)=compile cocl_args compile_state
# result=if ok 0(-1);
# r=send_result result
| r<>0
-> abort "compile_files 3";
-> compile_files compile compile_state
["quit"]
-> /* trace_n "quiting" */ compile_state;
_
-> abort "compile_files 4"
CC=gcc
CFLAGS=-pedantic -Wall -W -O
CPPFLAGS=
all: cDirectory.o ipc.o set_return_code_c.o
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>
#include "Clean.h"
#ifndef NAME_MAX
#define NAME_MAX 500
#endif
#define FALSE 0
#define TRUE (!FALSE)
// error codes:
#define NoDirError 0
#define OtherDirError -1
#define DoesntExist -2
#define BadName -3
#define NotEnoughSpace -4
#define AlreadyExists -5
#define NoPermission -6
#define MoveIntoOffspring -7
#define MoveAcrossDisks -8
#define NotYetRemovable -9
uid_t gUserId;
gid_t gGroupId;
struct DIR *gpDir;
struct dirent *gpDirent;
struct stat gFileStat;
char *gPath;
int gPathLength;
CleanStringVariable(gFileName,NAME_MAX+1);
static int unix_error_to_clean_error(int errCode)
{
switch(errCode) {
case ENOENT:
case ENOTDIR: return DoesntExist;
case ENAMETOOLONG: return BadName;
case EMLINK:
case ENOSPC: return NotEnoughSpace;
case EISDIR:
case EEXIST: return AlreadyExists;
case EPERM:
case EACCES:
case EROFS: return NoPermission;
case EINVAL: return MoveIntoOffspring;
case EXDEV: return MoveAcrossDisks;
case ENOTEMPTY: return NotYetRemovable;
default: return OtherDirError;
};
}
static int openSearch(const char *path, int length)
{
int i;
gPathLength = length;
gPath = (char*) malloc(gPathLength+NAME_MAX+2);
if (!gPath) {
gpDir = NULL;
return 0;
}
else {
memcpy(gPath, path, gPathLength);
gPath[gPathLength] = '\0';
gpDir = (struct DIR*) opendir(gPath);
if (!gpDir)
return unix_error_to_clean_error(errno);
gPath[gPathLength] = '/'; // filename will be added later
gUserId = getuid();
gGroupId = getgid();
return NoDirError;
};
}
int findFirstFileC(CleanString cs_path)
{
int errCode;
errCode = openSearch(CleanStringCharacters(cs_path), CleanStringLength(cs_path));
if (errCode)
return errCode;
else
return findNextFileC(0);
}
void getCommonFileInfoC(int also_get_file_name,
CleanString *pFileName, int *pFileSizeLow, int *pFileSizeHigh,
int *pYear, int *pMonth, int *pDay, int *pDayNr,
int *pHours, int *pMinutes, int *pSeconds,
int *pIsDirectory, int *pIsReadOnly)
// requires gFileName and gFileStat to be initialized
{
struct tm *pModificationTime;
int mask;
static int null = 0;
*pFileName = also_get_file_name ? (CleanString) gFileName : (CleanString) &null;
*pFileSizeLow = gFileStat.st_size;
*pFileSizeHigh = 0;
pModificationTime= localtime(&gFileStat.st_mtime);
*pYear = pModificationTime->tm_year+1900;
*pMonth = pModificationTime->tm_mon+1;
*pDay = pModificationTime->tm_mday;
*pDayNr = pModificationTime->tm_wday+1;
*pHours = pModificationTime->tm_hour;
*pMinutes = pModificationTime->tm_min;
*pSeconds = pModificationTime->tm_sec % 60;
*pIsDirectory = (gFileStat.st_mode & S_IFDIR) != 0;
mask = gUserId==gFileStat.st_uid ? S_IWUSR
: gGroupId==gFileStat.st_gid ? S_IWGRP
: S_IWOTH;
*pIsReadOnly = (gFileStat.st_mode & mask) == 0;
}
int findNextFileC(int dummy)
// return values: 0=ok, 1=no further files in directory
{
int i;
gpDirent = readdir((void*)gpDir);
if (!gpDirent)
return 1;
for(i=0; gpDirent->d_name[i]!='\0' && i<NAME_MAX; i++) {
CleanStringCharacters(gFileName)[i] = gpDirent->d_name[i];
gPath[gPathLength+1+i] = gpDirent->d_name[i];
};
CleanStringLength(gFileName)= i;
gPath[gPathLength+1+i] = '\0';
gFileStat.st_size = 0;
gFileStat.st_mode = 0;
lstat(gPath,&gFileStat);
return 0;
}
int getPlatformIdC(int dummy)
{
#define UnixPlatform 0
return UnixPlatform;
}
void getWindowsFileInfoC()
{}
void getMacFileInfoC()
{}
void getUnixFileInfoC(int *pModeBits, int *pOwnerUserId, int *pOwnerGroupId,
int *pLAYear, int *pLAMonth, int *pLADay, int *pLADayNr, // last access time
int *pLAHours, int *pLAMinutes, int *pLASeconds) // dito
{
struct tm *pModificationTime;
*pModeBits = gFileStat.st_mode;
*pOwnerUserId = gFileStat.st_uid;
*pOwnerGroupId = gFileStat.st_gid;
pModificationTime= localtime(&gFileStat.st_atime);
*pLAYear = pModificationTime->tm_year+1900;
*pLAMonth = pModificationTime->tm_mon+1;
*pLADay = pModificationTime->tm_mday;
*pLADayNr = pModificationTime->tm_wday+1;
*pLAHours = pModificationTime->tm_hour;
*pLAMinutes = pModificationTime->tm_min;
*pLASeconds = pModificationTime->tm_sec % 60;
}
void closeSearchC()
{
free(gPath);
if (gpDir)
closedir((void*)gpDir);
}
int findSingleFileC(CleanString cs_path)
{
int err,i,length;
char *path_chars;
gFileStat.st_size = 0;
gFileStat.st_mode = 0;
path_chars = CleanStringCharacters(cs_path);
if (lstat(path_chars,&gFileStat))
return unix_error_to_clean_error(errno);
i = CleanStringLength(cs_path)-2;
while (i>=0 && path_chars[i]!='/')
i--;
// the last path element ranges from path_chars[i+1] to path_chars[CleanStringLength(cs_path)-2]
length = CleanStringLength(cs_path)-2-i;
CleanStringLength(gFileName) = length;
memcpy(CleanStringCharacters(gFileName), path_chars+i+1, length);
return NoDirError;
}
void closeSingleSearchC()
{}
int createDirectoryC(CleanString cs_path)
{
int err;
err = mkdir(CleanStringCharacters(cs_path),
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
// access rights for newly created directory: rwx--x--x
if (err)
return unix_error_to_clean_error(errno);
else
return NoDirError;
}
int fremoveC(CleanString cs_path)
{
int err;
err = remove(CleanStringCharacters(cs_path));
if (err) {
if (errno==EEXIST)
return NotYetRemovable;
else
return unix_error_to_clean_error(errno);
}
else
return NoDirError;
}
// Try this code with slackware linux, if the testLinux program doesn't work
//int fremoveC(CleanString cs_path)
//{
// int err;
//
// err = unlink(CleanStringCharacters(cs_path));
// if (err) {
// if (errno==EPERM) {
// err = rmdir(CleanStringCharacters(cs_path));
// if (err)
// return unix_error_to_clean_error(errno);
// else
// return NoDirError;
// }
// else
// return unix_error_to_clean_error(errno);
// }
// else
// return NoDirError;
//}
#define OK 0
#define STRING_TOO_SMALL 1
int getCurrentDirectory_SE(CleanString cs)
{
if (getcwd(CleanStringCharacters(cs), CleanStringLength(cs))) {
// success. convert C String to Clean string
int i;
i = 0;
while(CleanStringCharacters(cs)[i]!='\0')
i++;
CleanStringLength(cs) = i;
return OK;
}
else {
// failure
if (errno==EACCES) {
// the permission to read the current directory was denied (how ever)
// return root directory
CleanStringLength(cs) = 1;
CleanStringCharacters(cs)[0] = '/';
return OK;
}
else
return STRING_TOO_SMALL;
};
}
void get_mac_dir_parent_and_name_C()
{
}
int setCurrentDirectoryC(CleanString csPath)
{
int err;
err = chdir(CleanStringCharacters(csPath));
if (err)
return unix_error_to_clean_error(errno);
else
return NoDirError;
}
void getMacDiskNameC()
{}
void get_windows_disk_available_bits_C()
{}
void macRenameC()
{}
void macMoveC()
{}
int fmoveC(int overwrite, CleanString from, CleanString to)
{
int err,clean_err;
if (overwrite) {
err = rename(CleanStringCharacters(from), CleanStringCharacters(to));
if (err && errno==ENOTDIR) {
// from is a directory and to a file
// try again after removing to
err = remove(CleanStringCharacters(to));
if (!err)
err = rename(CleanStringCharacters(from), CleanStringCharacters(to));
};
clean_err = err ? unix_error_to_clean_error(errno) : NoDirError;
}
else {
struct stat fileStat;
if (stat(CleanStringCharacters(to),&fileStat)) {
err = rename(CleanStringCharacters(from), CleanStringCharacters(to));
clean_err = err ? unix_error_to_clean_error(errno) : NoDirError;
}
else
clean_err = AlreadyExists;
};
return clean_err;
}
/*
Unix clm/cocl interface
Ronny Wichers Schreur
*/
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <strings.h>
/*
Clean string
============
*/
typedef struct clean_string {int length; char chars [1]; } *CleanString;
# define Clean(ignore)
# include "ipc.h"
static void
log (char *format, ...)
{
#ifdef DEBUG
va_list ap;
va_start (ap, format);
(void) fputs(" cocl: ", stderr);
(void) vfprintf(stderr, format, ap);
va_end(ap);
#else /* ifndef DEBUG */
#endif
}
static char *
ConvertCleanString (CleanString string)
{
int length;
char *copy;
length = string->length;
copy = malloc (length+1);
strncpy (copy, string->chars, length);
copy [length] = '\0';
return (copy);
} /* ConvertCleanString */
static FILE *commands, *results;
# define COMMAND_BUFFER_SIZE 1024
static char command_buffer[COMMAND_BUFFER_SIZE];
static void
crash (void)
{
int *p;
p = NULL;
log ("crashing\n");
*p = 0;
} /* crash */
static void
hang (void)
{
log ("hanging\n");
for (;;)
;
} /* hang */
int open_pipes (CleanString commands_clean, CleanString results_clean)
{
char *commands_name, *results_name;
commands_name = ConvertCleanString (commands_clean);
results_name = ConvertCleanString (results_clean);
if ((commands = fopen(commands_name, "r")) == NULL)
{
log("commands = %s\n",commands_name);
perror("fopen commands");
return -1;
}
if ((results = fopen(results_name, "w")) == NULL)
{
log("results = %s\n",results_name);
perror("fopen results");
return -1;
}