1 /* 2 * 3 * Generate module.c from module.in and Makefile.am or Makefile. 4 * 5 * Copyright (C) 2004-2007 Peter Johnson 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <ctype.h> 32 33 #include "compat-queue.h" 34 35 #define MAXNAME 128 36 #define MAXLINE 1024 37 #define MAXMODULES 128 38 #define MAXINCLUDES 256 39 40 typedef struct include { 41 STAILQ_ENTRY(include) link; 42 char *filename; 43 } include; 44 45 int 46 main(int argc, char *argv[]) 47 { 48 FILE *in, *out; 49 char *str; 50 int i; 51 size_t len; 52 char *strp; 53 char *modules[MAXMODULES]; 54 int num_modules = 0; 55 STAILQ_HEAD(includehead, include) includes = 56 STAILQ_HEAD_INITIALIZER(includes); 57 include *inc; 58 int isam = 0; 59 int linecont = 0; 60 char *outfile; 61 62 if (argc != 4) { 63 fprintf(stderr, "Usage: %s <module.in> <Makefile[.am]> <outfile>\n", argv[0]); 64 return EXIT_FAILURE; 65 } 66 67 outfile = argv[3]; 68 str = malloc(MAXLINE); 69 70 /* Starting with initial input Makefile, look for include <file> or 71 * YASM_MODULES += <module>. Note this currently doesn't handle 72 * a relative starting path. 73 */ 74 len = strlen(argv[2]); 75 inc = malloc(sizeof(include)); 76 inc->filename = malloc(len+1); 77 strcpy(inc->filename, argv[2]); 78 STAILQ_INSERT_TAIL(&includes, inc, link); 79 80 isam = argv[2][len-2] == 'a' && argv[2][len-1] == 'm'; 81 82 while (!STAILQ_EMPTY(&includes)) { 83 inc = STAILQ_FIRST(&includes); 84 STAILQ_REMOVE_HEAD(&includes, link); 85 in = fopen(inc->filename, "rt"); 86 if (!in) { 87 fprintf(stderr, "Could not open `%s'.\n", inc->filename); 88 return EXIT_FAILURE; 89 } 90 free(inc->filename); 91 free(inc); 92 93 while (fgets(str, MAXLINE, in)) { 94 /* Strip off any trailing whitespace */ 95 len = strlen(str); 96 if (len > 0) { 97 strp = &str[len-1]; 98 while (len > 0 && isspace(*strp)) { 99 *strp-- = '\0'; 100 len--; 101 } 102 } 103 104 strp = str; 105 106 /* Skip whitespace */ 107 while (isspace(*strp)) 108 strp++; 109 110 /* Skip comments */ 111 if (*strp == '#') 112 continue; 113 114 /* If line continuation, skip to continue copy */ 115 if (linecont) 116 goto keepgoing; 117 118 /* Check for include if original input is .am file */ 119 if (isam && strncmp(strp, "include", 7) == 0 && isspace(strp[7])) { 120 strp += 7; 121 while (isspace(*strp)) 122 strp++; 123 /* Build new include and add to end of list */ 124 inc = malloc(sizeof(include)); 125 inc->filename = malloc(strlen(strp)+1); 126 strcpy(inc->filename, strp); 127 STAILQ_INSERT_TAIL(&includes, inc, link); 128 continue; 129 } 130 131 /* Check for YASM_MODULES = or += */ 132 if (strncmp(strp, "YASM_MODULES", 12) != 0) 133 continue; 134 strp += 12; 135 while (isspace(*strp)) 136 strp++; 137 if (strncmp(strp, "+=", 2) != 0 && *strp != '=') 138 continue; 139 if (*strp == '+') 140 strp++; 141 strp++; 142 while (isspace(*strp)) 143 strp++; 144 145 keepgoing: 146 /* Check for continuation */ 147 if (len > 0 && str[len-1] == '\\') { 148 str[len-1] = '\0'; 149 while (isspace(*strp)) 150 *strp-- = '\0'; 151 linecont = 1; 152 } else 153 linecont = 0; 154 155 while (*strp != '\0') { 156 /* Copy module name */ 157 modules[num_modules] = malloc(MAXNAME); 158 len = 0; 159 while (*strp != '\0' && !isspace(*strp)) 160 modules[num_modules][len++] = *strp++; 161 modules[num_modules][len] = '\0'; 162 num_modules++; 163 164 while (isspace(*strp)) 165 strp++; 166 } 167 } 168 fclose(in); 169 } 170 171 out = fopen(outfile, "wt"); 172 173 if (!out) { 174 fprintf(stderr, "Could not open `%s'.\n", outfile); 175 return EXIT_FAILURE; 176 } 177 178 fprintf(out, "/* This file auto-generated by genmodule.c" 179 " - don't edit it */\n\n"); 180 181 in = fopen(argv[1], "rt"); 182 if (!in) { 183 fprintf(stderr, "Could not open `%s'.\n", argv[1]); 184 fclose(out); 185 remove(outfile); 186 return EXIT_FAILURE; 187 } 188 189 len = 0; 190 while (fgets(str, MAXLINE, in)) { 191 if (strncmp(str, "MODULES_", 8) == 0) { 192 len = 0; 193 strp = str+8; 194 while (*strp != '\0' && *strp != '_') { 195 len++; 196 strp++; 197 } 198 *strp = '\0'; 199 200 for (i=0; i<num_modules; i++) { 201 if (strncmp(modules[i], str+8, len) == 0) { 202 fprintf(out, " {\"%s\", &yasm_%s_LTX_%s},\n", 203 modules[i]+len+1, modules[i]+len+1, str+8); 204 } 205 } 206 } else if (strncmp(str, "EXTERN_LIST", 11) == 0) { 207 for (i=0; i<num_modules; i++) { 208 strcpy(str, modules[i]); 209 strp = str; 210 while (*strp != '\0' && *strp != '_') 211 strp++; 212 *strp++ = '\0'; 213 214 fprintf(out, "extern yasm_%s_module yasm_%s_LTX_%s;\n", 215 str, strp, str); 216 } 217 } else 218 fputs(str, out); 219 } 220 221 fclose(in); 222 fclose(out); 223 224 for (i=0; i<num_modules; i++) 225 free(modules[i]); 226 free(str); 227 228 return EXIT_SUCCESS; 229 } 230