Back to index

lightning-sunbird  0.9+nobinonly
xpidl.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * Main xpidl program entry point.
00040  */
00041 
00042 #include "xpidl.h"
00043 
00044 static ModeData modes[] = {
00045     {"header",  "Generate C++ header",         "h",    xpidl_header_dispatch},
00046     {"typelib", "Generate XPConnect typelib",  "xpt",  xpidl_typelib_dispatch},
00047     {"doc",     "Generate HTML documentation", "html", xpidl_doc_dispatch},
00048     {"java",    "Generate Java interface",     "java", xpidl_java_dispatch},
00049     {0,         0,                             0,      0}
00050 };
00051 
00052 static ModeData *
00053 FindMode(char *mode)
00054 {
00055     int i;
00056     for (i = 0; modes[i].mode; i++) {
00057         if (!strcmp(modes[i].mode, mode))
00058             return &modes[i];
00059     }
00060     return NULL;
00061 }
00062 
00063 gboolean enable_debug               = FALSE;
00064 gboolean enable_warnings            = FALSE;
00065 gboolean verbose_mode               = FALSE;
00066 gboolean emit_typelib_annotations   = FALSE;
00067 gboolean explicit_output_filename   = FALSE;
00068 
00069 /* The following globals are explained in xpt_struct.h */
00070 PRUint8  major_version              = XPT_MAJOR_VERSION;
00071 PRUint8  minor_version              = XPT_MINOR_VERSION;
00072 
00073 static char xpidl_usage_str[] =
00074 "Usage: %s -m mode [-w] [-v] [-t version number]\n"
00075 "          [-I path] [-o basename | -e filename.ext]\n"
00076 "          [-p Java package] filename.idl\n"
00077 "       -a emit annotations to typelib\n"
00078 "       -w turn on warnings (recommended)\n"
00079 "       -v verbose mode (NYI)\n"
00080 "       -t create a typelib of a specific version number\n"
00081 "       -I add entry to start of include path for ``#include \"nsIThing.idl\"''\n"
00082 "       -o use basename (e.g. ``/tmp/nsIThing'') for output\n"
00083 "       -e use explicit output filename\n"
00084 "       -p specify package name (Java mode only)\n"
00085 "       -m specify output mode:\n";
00086 
00087 static void
00088 xpidl_usage(int argc, char *argv[])
00089 {
00090     int i;
00091     fprintf(stderr, xpidl_usage_str, argv[0]);
00092     for (i = 0; modes[i].mode; i++) {
00093         fprintf(stderr, "          %-12s  %-30s (.%s)\n", modes[i].mode,
00094                 modes[i].modeInfo, modes[i].suffix);
00095     }
00096 }
00097 
00098 #if defined(XP_MAC) && defined(XPIDL_PLUGIN)
00099 #define main xpidl_main
00100 int xpidl_main(int argc, char *argv[]);
00101 #endif
00102 
00103 int main(int argc, char *argv[])
00104 {
00105     int i;
00106     IncludePathEntry *inc, *inc_head, **inc_tail;
00107     char *file_basename = NULL, *package = NULL;
00108     ModeData *mode = NULL;
00109     gboolean create_old_typelib = FALSE;
00110 
00111     /* turn this on for extra checking of our code */
00112 /*    IDL_check_cast_enable(TRUE); */
00113 
00114     inc_head = xpidl_malloc(sizeof *inc);
00115 #ifndef XP_MAC
00116     inc_head->directory = ".";
00117 #else
00118     inc_head->directory = "";
00119 #endif
00120     inc_head->next = NULL;
00121     inc_tail = &inc_head->next;
00122 
00123     for (i = 1; i < argc; i++) {
00124         if (argv[i][0] != '-')
00125             break;
00126         switch (argv[i][1]) {
00127           case '-':
00128             argc++;             /* pretend we didn't see this */
00129             /* fall through */
00130           case 0:               /* - is a legal input filename (stdin)  */
00131             goto done_options;
00132           case 'a':
00133             emit_typelib_annotations = TRUE;
00134             break;
00135           case 'w':
00136             enable_warnings = TRUE;
00137             break;
00138           case 'v':
00139             verbose_mode = TRUE;
00140             break;
00141           case 't':
00142           {
00143             /* Parse for "-t version number" and store it into global boolean
00144              * and string variables.
00145              */
00146             const gchar* typelib_version_string = NULL;
00147 
00148             /* 
00149              * If -t is the last argument on the command line, we have a problem
00150              */
00151 
00152             if (i + 1 == argc) {
00153                 fprintf(stderr, "ERROR: missing version number after -t\n");
00154                 xpidl_usage(argc, argv);
00155                 return 1;
00156             }
00157 
00158             /* Do not allow more than one "-t" definition */
00159             if (create_old_typelib) {
00160                 fprintf(stderr,
00161                         "ERROR: -t argument used twice. "
00162                         "Cannot specify more than one version\n");
00163                 xpidl_usage(argc, argv);
00164                 return 1;
00165             }
00166 
00167             /*
00168              * Assume that the argument after "-t" is the version number string
00169              * and search for it in our internal list of acceptable version
00170              * numbers.
00171              */
00172             switch (XPT_ParseVersionString(argv[++i], &major_version, 
00173                                            &minor_version)) {
00174               case XPT_VERSION_CURRENT:
00175                 break; 
00176               case XPT_VERSION_OLD: 
00177                 create_old_typelib = TRUE;
00178                 break; 
00179               case XPT_VERSION_UNSUPPORTED: 
00180                 fprintf(stderr, "ERROR: version \"%s\" not supported.\n", 
00181                         argv[i]);
00182                 xpidl_usage(argc, argv);
00183                 return 1;          
00184               case XPT_VERSION_UNKNOWN: 
00185               default:
00186                 fprintf(stderr, "ERROR: version \"%s\" not recognised.\n", 
00187                         argv[i]);
00188                 xpidl_usage(argc, argv);
00189                 return 1;          
00190             }
00191             break;
00192           }
00193           case 'I':
00194             if (argv[i][2] == '\0' && i == argc) {
00195                 fputs("ERROR: missing path after -I\n", stderr);
00196                 xpidl_usage(argc, argv);
00197                 return 1;
00198             }
00199             inc = xpidl_malloc(sizeof *inc);
00200             if (argv[i][2] == '\0') {
00201                 /* is it the -I foo form? */
00202                 inc->directory = argv[++i];
00203             } else {
00204                 /* must be the -Ifoo form.  Don't preincrement i. */
00205                 inc->directory = argv[i] + 2;
00206             }
00207 #ifdef DEBUG_shaver_includes
00208             fprintf(stderr, "adding %s to include path\n", inc->directory);
00209 #endif
00210             inc->next = NULL;
00211             *inc_tail = inc;
00212             inc_tail = &inc->next;
00213             break;
00214           case 'o':
00215             if (i == argc) {
00216                 fprintf(stderr, "ERROR: missing basename after -o\n");
00217                 xpidl_usage(argc, argv);
00218                 return 1;
00219             }
00220             file_basename = argv[++i];
00221             explicit_output_filename = FALSE;
00222             break;
00223           case 'e':
00224             if (i == argc) {
00225                 fprintf(stderr, "ERROR: missing basename after -e\n");
00226                 xpidl_usage(argc, argv);
00227                 return 1;
00228             }
00229             file_basename = argv[++i];
00230             explicit_output_filename = TRUE;
00231             break;
00232           case 'm':
00233             if (i + 1 == argc) {
00234                 fprintf(stderr, "ERROR: missing modename after -m\n");
00235                 xpidl_usage(argc, argv);
00236                 return 1;
00237             }
00238             if (mode) {
00239                 fprintf(stderr,
00240                         "ERROR: must specify exactly one mode "
00241                         "(first \"%s\", now \"%s\")\n", mode->mode,
00242                         argv[i + 1]);
00243                 xpidl_usage(argc, argv);
00244                 return 1;
00245             }
00246             mode = FindMode(argv[++i]);
00247             if (!mode) {
00248                 fprintf(stderr, "ERROR: unknown mode \"%s\"\n", argv[i]);
00249                 xpidl_usage(argc, argv);
00250                 return 1;
00251             }
00252             break;
00253           case 'p':
00254             if (i + 1 == argc) {
00255                 fprintf(stderr, "ERROR: missing package name after -p\n");
00256                 xpidl_usage(argc, argv);
00257                 return 1;
00258             }
00259             if (package) {
00260                 fprintf(stderr,
00261                         "ERROR: must specify exactly one package "
00262                         "(first \"%s\", now \"%s\")\n", package,
00263                         argv[i + 1]);
00264                 xpidl_usage(argc, argv);
00265                 return 1;
00266             }
00267             package = argv[++i];
00268             if (!package) {
00269                 fprintf(stderr, "ERROR: unknown package \"%s\"\n", argv[i]);
00270                 xpidl_usage(argc, argv);
00271                 return 1;
00272             }
00273             break;
00274           default:
00275             fprintf(stderr, "unknown option %s\n", argv[i]);
00276             xpidl_usage(argc, argv);
00277             return 1;
00278         }
00279     }
00280  done_options:
00281     if (!mode) {
00282         fprintf(stderr, "ERROR: must specify output mode\n");
00283         xpidl_usage(argc, argv);
00284         return 1;
00285     }
00286     if (argc != i + 1) {
00287         fprintf(stderr, "ERROR: extra arguments after input file\n");
00288     }
00289 
00290     /*
00291      * Don't try to process multiple files, given that we don't handle -o
00292      * multiply.
00293      */
00294     if (xpidl_process_idl(argv[i], inc_head, file_basename, package, mode))
00295         return 0;
00296 
00297     return 1;
00298 }