Files
mercury/util/mkinit_common.c
Zoltan Somogyi 2315f1660e Replace /* */ comments with // comments in util.
util/mdemangle.c:
util/mfiltercc.c:
util/mkinit_common.c:
util/pad_backslash.c:
    As above. The other .c files in util already used // comments.
2023-03-19 00:16:22 +11:00

377 lines
9.1 KiB
C

//---------------------------------------------------------------------------//
// vim:sw=4 ts=4 expandtab
//---------------------------------------------------------------------------//
//
// Copyright (C) 1995-2007 The University of Melbourne.
// This file may only be copied under the terms of the GNU General
// Public License - see the file COPYING in the Mercury distribution.
//
// File: mkinit_common.c
// Main authors: zs, fjh
//
// Common code previously shared by mkinit.c and mkinit_erl.c.
//
//---------------------------------------------------------------------------//
// mercury_std.h includes mercury_regs.h, and must precede system headers.
#include "mercury_conf.h"
#include "mercury_std.h"
#include "mercury_array_macros.h"
#include "mkinit_common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifdef MR_HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef MR_HAVE_UNISTD_H
#include <unistd.h>
#endif
// --- global variables ---
const char *MR_progname = NULL;
int num_errors = 0;
int num_files;
char **files = NULL;
static int size_of_files;
// List of directories to search for init files.
static String_List *init_file_dirs = NULL;
// Pointer to tail of the init_file_dirs list.
static String_List **init_file_dirs_tail = &init_file_dirs;
// --- adjustable limits ---
#define MAXFILENAME 4096 // maximum file name length
#define NUMFILES 128 // initial size of files array
#define FACTOR 2 // factor to increase files array by
// --- function prototypes ---
static char *find_init_file(const char *base_name);
static MR_bool file_exists(const char *filename);
//---------------------------------------------------------------------------//
void
process_file_list_file(char *filename)
{
FILE *fp;
char *line;
fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "%s: error opening file `%s': %s\n",
MR_progname, filename, strerror(errno));
num_errors++;
return;
}
// Initialize the files structure, if required.
if (files == NULL) {
num_files = 0;
size_of_files = NUMFILES;
files = (char **) checked_malloc(sizeof(char *) * NUMFILES);
}
while ((line = read_line(filename, fp, MAXFILENAME)) != NULL) {
// Ignore blank lines.
if (line[0] != '\0') {
if (num_files >= size_of_files) {
size_of_files *= FACTOR;
files = (char **)
checked_realloc(files, size_of_files * sizeof(char *));
if (files == NULL) {
fprintf(stderr, "%s: unable to realloc\n", MR_progname);
exit(EXIT_FAILURE);
}
}
files[num_files] = line;
num_files++;
}
}
}
//---------------------------------------------------------------------------//
//
// If the `-o' option was used to specify the output file,
// and the file name specified is not `-' (which we take to mean stdout),
// then reassign stdout to the specified file.
//
void
set_output_file(const char *output_file_name)
{
if (output_file_name != NULL) {
FILE *result = freopen(output_file_name, "w", stdout);
if (result == NULL) {
fprintf(stderr,
"%s: error opening output file `%s': %s\n",
MR_progname, output_file_name, strerror(errno));
exit(EXIT_FAILURE);
}
}
}
//---------------------------------------------------------------------------//
// Add the directory name to the end of the search path for `.init' files.
void
add_init_file_dir(const char *dir_name)
{
String_List *tmp_slist;
tmp_slist = (String_List *) checked_malloc(sizeof(String_List));
tmp_slist->next = NULL;
tmp_slist->data = (char *) checked_malloc(strlen(dir_name) + 1);
strcpy(tmp_slist->data, dir_name);
*init_file_dirs_tail = tmp_slist;
init_file_dirs_tail = &tmp_slist->next;
}
// Scan the list of files for ones not found in the current directory,
// and replace them with their full path equivalent if they are found
// in the list of search directories.
void
do_path_search(char **lfiles, int lnum_files)
{
int filenum;
char *init_file;
for (filenum = 0; filenum < lnum_files; filenum++) {
init_file = find_init_file(lfiles[filenum]);
if (init_file != NULL) {
lfiles[filenum] = init_file;
}
}
}
// Search the init file directory list to locate the file.
// If the file is in the current directory or is not in any of the
// search directories, then return NULL. Otherwise return the full
// path name to the file.
//
// It is the caller's responsibility to free the returned buffer
// holding the full path name when it is no longer needed.
static char *
find_init_file(const char *base_name)
{
char *filename;
char *dirname;
String_List *dir_ptr;
size_t dirlen;
size_t baselen;
size_t len;
if (file_exists(base_name)) {
// File is in current directory, so no search required.
return NULL;
}
baselen = strlen(base_name);
for (dir_ptr = init_file_dirs; dir_ptr != NULL; dir_ptr = dir_ptr->next) {
dirname = dir_ptr->data;
dirlen = strlen(dirname);
len = dirlen + 1 + baselen;
filename = (char *) checked_malloc(len + 1);
strcpy(filename, dirname);
filename[dirlen] = '/';
strcpy(filename + dirlen + 1, base_name);
if (file_exists(filename)) {
return filename;
}
free(filename);
}
// Did not find file.
return NULL;
}
// Check whether a file exists.
static MR_bool
file_exists(const char *filename)
{
#ifdef MR_HAVE_SYS_STAT_H
struct stat buf;
return (stat(filename, &buf) == 0);
#else
FILE *f;
f = fopen(filename, "rb");
if (f != NULL) {
fclose(f);
return MR_TRUE;
} else {
return MR_FALSE;
}
#endif
}
//---------------------------------------------------------------------------//
// Read a line from a file, and return a pointer to a malloc'd buffer
// holding the line (without the final newline). If EOF occurs on a
// nonempty line, treat the EOF as a newline; if EOF occurs on an empty
// line, return NULL.
char *
read_line(const char *filename, FILE *fp, size_t max)
{
char *buf;
int c;
size_t i;
buf = checked_malloc(max + 1);
i = 0;
while ((c = getc(fp)) != EOF && c != '\n') {
if (i >= max) {
fprintf(stderr, "%s: line too long in file `%s'\n",
MR_progname, filename);
num_errors++;
return NULL;
}
buf[i++] = (char) c;
}
if (c == '\n' || i > 0) {
if (i >= max) {
fprintf(stderr, "%s: line too long in file `%s'\n",
MR_progname, filename);
num_errors++;
return NULL;
}
buf[i] = '\0';
return buf;
} else {
free(buf);
return NULL;
}
}
int
get_line(FILE *file, char *line, int line_max)
{
int c;
int num_chars;
int limit;
num_chars = 0;
limit = line_max - 2;
while ((c = getc(file)) != EOF && c != '\n') {
if (num_chars < limit) {
line[num_chars++] = (char) c;
}
}
if (c == '\n' || num_chars > 0) {
line[num_chars++] = '\n';
}
line[num_chars] = '\0';
#ifdef CHECK_GET_LINE
if (check_fp != NULL) {
fprintf(check_fp, "%s", line);
}
#endif
return num_chars;
}
//---------------------------------------------------------------------------//
void *
checked_malloc(size_t size)
{
void *ptr;
ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
return ptr;
}
void *
checked_realloc(void *old_ptr, size_t size)
{
void *ptr;
ptr = realloc(old_ptr, size);
if (ptr == NULL) {
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
return ptr;
}
char *
checked_strdup(const char *str)
{
char *mem;
mem = checked_malloc(strlen(str) + 1);
strcpy(mem, str);
return mem;
}
char *
checked_strdupcat(const char *str, const char *suffix)
{
char *mem;
mem = checked_malloc(strlen(str) + strlen(suffix) + 1);
strcpy(mem, str);
strcat(mem, suffix);
return mem;
}
//---------------------------------------------------------------------------//
#ifndef MR_HAVE_STRERROR
// Apparently SunOS 4.1.3 doesn't have strerror()
// (!%^&!^% non-ANSI systems, grumble...)
//
// This code is duplicated in runtime/mercury_prof.c.
extern int sys_nerr;
extern char *sys_errlist[];
char *
strerror(int errnum)
{
if (errnum >= 0 && errnum < sys_nerr && sys_errlist[errnum] != NULL) {
return sys_errlist[errnum];
} else {
static char buf[30];
sprintf(buf, "Error %d", errnum);
return buf;
}
}
#endif
//---------------------------------------------------------------------------//