blob: 867d93a5b23ef18903b25baffbc77816740bea25 [file] [log] [blame]
/*
*
* Generate module.c from module.in and Makefile.am or Makefile.
*
* Copyright (C) 2004-2007 Peter Johnson
*
* 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 THE AUTHOR AND OTHER CONTRIBUTORS ``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 THE AUTHOR OR OTHER 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "compat-queue.h"
#define OUTPUT "module.c"
#define MAXNAME 128
#define MAXLINE 1024
#define MAXMODULES 128
#define MAXINCLUDES 256
typedef struct include {
STAILQ_ENTRY(include) link;
char *filename;
} include;
int
main(int argc, char *argv[])
{
FILE *in, *out;
char *str;
int i;
size_t len;
char *strp;
char *modules[MAXMODULES];
int num_modules = 0;
STAILQ_HEAD(includehead, include) includes =
STAILQ_HEAD_INITIALIZER(includes);
include *inc;
int isam = 0;
int linecont = 0;
if (argc != 3) {
fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]>\n", argv[0]);
return EXIT_FAILURE;
}
str = malloc(MAXLINE);
/* Starting with initial input Makefile, look for include <file> or
* YASM_MODULES += <module>. Note this currently doesn't handle
* a relative starting path.
*/
len = strlen(argv[2]);
inc = malloc(sizeof(include));
inc->filename = malloc(len+1);
strcpy(inc->filename, argv[2]);
STAILQ_INSERT_TAIL(&includes, inc, link);
isam = argv[2][len-2] == 'a' && argv[2][len-1] == 'm';
while (!STAILQ_EMPTY(&includes)) {
inc = STAILQ_FIRST(&includes);
STAILQ_REMOVE_HEAD(&includes, link);
in = fopen(inc->filename, "rt");
if (!in) {
fprintf(stderr, "Could not open `%s'.\n", inc->filename);
return EXIT_FAILURE;
}
free(inc->filename);
free(inc);
while (fgets(str, MAXLINE, in)) {
/* Strip off any trailing whitespace */
len = strlen(str);
if (len > 0) {
strp = &str[len-1];
while (len > 0 && isspace(*strp)) {
*strp-- = '\0';
len--;
}
}
strp = str;
/* Skip whitespace */
while (isspace(*strp))
strp++;
/* Skip comments */
if (*strp == '#')
continue;
/* If line continuation, skip to continue copy */
if (linecont)
goto keepgoing;
/* Check for include if original input is .am file */
if (isam && strncmp(strp, "include", 7) == 0 && isspace(strp[7])) {
strp += 7;
while (isspace(*strp))
strp++;
/* Build new include and add to end of list */
inc = malloc(sizeof(include));
inc->filename = malloc(strlen(strp)+1);
strcpy(inc->filename, strp);
STAILQ_INSERT_TAIL(&includes, inc, link);
continue;
}
/* Check for YASM_MODULES = or += */
if (strncmp(strp, "YASM_MODULES", 12) != 0)
continue;
strp += 12;
while (isspace(*strp))
strp++;
if (strncmp(strp, "+=", 2) != 0 && *strp != '=')
continue;
if (*strp == '+')
strp++;
strp++;
while (isspace(*strp))
strp++;
keepgoing:
/* Check for continuation */
if (len > 0 && str[len-1] == '\\') {
str[len-1] = '\0';
while (isspace(*strp))
*strp-- = '\0';
linecont = 1;
} else
linecont = 0;
while (*strp != '\0') {
/* Copy module name */
modules[num_modules] = malloc(MAXNAME);
len = 0;
while (*strp != '\0' && !isspace(*strp))
modules[num_modules][len++] = *strp++;
modules[num_modules][len] = '\0';
num_modules++;
while (isspace(*strp))
strp++;
}
}
fclose(in);
}
out = fopen(OUTPUT, "wt");
if (!out) {
fprintf(stderr, "Could not open `%s'.\n", OUTPUT);
return EXIT_FAILURE;
}
fprintf(out, "/* This file auto-generated by genmodule.c"
" - don't edit it */\n\n");
in = fopen(argv[1], "rt");
if (!in) {
fprintf(stderr, "Could not open `%s'.\n", argv[1]);
fclose(out);
remove(OUTPUT);
return EXIT_FAILURE;
}
len = 0;
while (fgets(str, MAXLINE, in)) {
if (strncmp(str, "MODULES_", 8) == 0) {
len = 0;
strp = str+8;
while (*strp != '\0' && *strp != '_') {
len++;
strp++;
}
*strp = '\0';
for (i=0; i<num_modules; i++) {
if (strncmp(modules[i], str+8, len) == 0) {
fprintf(out, " {\"%s\", &yasm_%s_LTX_%s},\n",
modules[i]+len+1, modules[i]+len+1, str+8);
}
}
} else if (strncmp(str, "EXTERN_LIST", 11) == 0) {
for (i=0; i<num_modules; i++) {
strcpy(str, modules[i]);
strp = str;
while (*strp != '\0' && *strp != '_')
strp++;
*strp++ = '\0';
fprintf(out, "extern yasm_%s_module yasm_%s_LTX_%s;\n",
str, strp, str);
}
} else
fputs(str, out);
}
fclose(in);
fclose(out);
for (i=0; i<num_modules; i++)
free(modules[i]);
free(str);
return EXIT_SUCCESS;
}