blob: 56220fa7101c7b3e071e3e394f83a372adc57f5f [file] [log] [blame]
/*
* Copyright (C) 2003, 2004, 2005 Filip Pizlo. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY FILIP PIZLO ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FILIP PIZLO OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "gpc_internal.h"
#include "tsf_format.h"
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>
/* code generation debugging */
/* NOTE: It is now the case that the count may be incremented multiple times,
* in order to insure that files are not overwritten. This allows multiple
* processes to use the same directory for code gen debugging. However, the
* multi-increment appproach may be overkill, since I could have probably just
* as well have used the PID. */
static volatile uint32_t count=0;
static tsf_once_t once_control = TSF_ONCE_INIT;
static tsf_mutex_t count_lock;
static void count_init(void) {
tsf_mutex_init(&count_lock);
}
static uint32_t next_count() {
uint32_t result;
tsf_once(&once_control, count_init);
tsf_mutex_lock(&count_lock);
result=count++;
tsf_mutex_unlock(&count_lock);
return result;
}
void gpc_dyncc_code_gen_debug(const char *type,
const char *src_filename) {
const char *tsf_code_gen_debug=getenv("TSF_CODE_GEN_DEBUG");
const char *tsf_code_gen_debug_path;
char *dest_filename;
int fd_src,fd_trg;
uint32_t cur_cnt;
if (tsf_code_gen_debug==NULL || strcasecmp(tsf_code_gen_debug,"YES")) {
return;
}
tsf_code_gen_debug_path=getenv("TSF_CODE_GEN_DEBUG_PATH");
if (tsf_code_gen_debug_path==NULL) {
return;
}
fd_src=open(src_filename,O_RDONLY);
if (fd_src<0) {
return;
}
/* loop until we hit a filename that isn't in use */
for (cur_cnt=count;;cur_cnt=next_count()) {
dest_filename=tsf_asprintf("%s/" fui32 "_%s",
tsf_code_gen_debug_path,
cur_cnt,
type);
if (dest_filename==NULL) {
close(fd_src);
return;
}
fd_trg=open(dest_filename,O_CREAT|O_EXCL|O_WRONLY,0600);
free(dest_filename);
if (fd_trg>=0) {
break;
}
if (errno!=EEXIST) {
close(fd_src);
return;
}
}
for (;;) {
char buf[1024];
int res=read(fd_src,buf,sizeof(buf));
if (res<=0) {
break;
}
if (write(fd_trg,buf,res)!=res) {
break;
}
}
close(fd_src);
close(fd_trg);
}
void gpc_code_gen_debug(const char *type,
gpc_proto_t *proto) {
const char *tsf_code_gen_debug=getenv("TSF_CODE_GEN_DEBUG");
const char *tsf_code_gen_debug_path;
char *dest_filename;
FILE *out;
uint32_t cur_cnt;
/* printf("dumping %s\n",type); */
if (tsf_code_gen_debug==NULL || strcasecmp(tsf_code_gen_debug,"YES")) {
return;
}
tsf_code_gen_debug_path=getenv("TSF_CODE_GEN_DEBUG_PATH");
if (tsf_code_gen_debug_path==NULL) {
return;
}
for (cur_cnt=count;;cur_cnt=next_count()) {
int fd;
dest_filename=tsf_asprintf("%s/" fui32 "_%s",
tsf_code_gen_debug_path,
cur_cnt,
type);
if (dest_filename==NULL) {
return;
}
fd=open(dest_filename,O_CREAT|O_EXCL|O_WRONLY,0600);
free(dest_filename);
if (fd>=0) {
out=fdopen(fd,"w");
if (out==NULL) {
close(fd);
return;
}
break;
}
if (errno!=EEXIST) {
/* printf("error not eexist\n"); */
return;
}
}
gpc_proto_print(proto,out);
fclose(out);
}
/* stupid stuff */
void gpc_unlink_free(char *name) {
unlink(name);
free(name);
}
void gpc_rmdir_free(char *name) {
rmdir(name);
free(name);
}
/* this isn't a real rm -rf; it only goes down one level. */
void gpc_rmdashrf_free(char *name) {
DIR *dir;
dir=opendir(name);
if (dir!=NULL) {
for (;;) {
struct dirent entry,*result=NULL;
int res=readdir_r(dir,&entry,&result);
if (res!=0 || result==NULL) {
break;
}
if (strcmp(entry.d_name,".") &&
strcmp(entry.d_name,"..")) {
char *flnm=tsf_asprintf("%s/%s",name,entry.d_name);
if (flnm!=NULL) {
unlink(flnm);
free(flnm);
}
}
}
closedir(dir);
rmdir(name);
}
free(name);
}