Home | History | Annotate | Download | only in libyasm
      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