ARPDAS_QNX6 1.0
compiler.c
Go to the documentation of this file.
00001 /* compiler.c Support routines for compilers */
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <stdarg.h>
00005 #include <string.h>
00006 #include <unistd.h>
00007 #include <assert.h>
00008 #include "nortlib.h"
00009 #include "compiler.h"
00010 char rcsid_compiler_c[] =
00011         "$Header: /cvsroot/arp-das/nortlib2/src/compiler.c,v 1.10 2009/09/10 17:27:34 ntallen Exp $";
00012 
00013 /* The idea here is to provide common functionality for compilers.
00014    This includes standard options, more or less as supported by
00015    tmc. The common options will include:
00016    
00017          -q print_usage
00018          -k keep output file on error
00019          -o specify output file name
00020          -v increase verbosity level
00021          -w treat warnings as errors
00022 
00023    Also, multiple input files are handled via yywrap
00024    and error messages are handled via standard nl_error
00025    hooks. To wit, the following initializations are
00026    required:
00027    
00028    Developer must supply a definition for nl_error which
00029    points to the error routine.
00030    
00031    Developer must supply definintion of opt_string.
00032 
00033    Developer must place the following code in a lex source:
00034          #ifdef yywrap
00035            #undef yywrap
00036          #endif
00037          int yywrap(void);
00038    This can be accomplished by including compiler.h
00039 */
00040 FILE *ofile = NULL;
00041 extern FILE *yyin;
00042 short compile_options = CO_IGN_WARN;
00043 char *input_filename = NULL;
00044 char *output_filename = NULL;
00045 int input_linenumber = 0;
00046 int error_level = 0;
00047 ll_of_str input_files;
00048 
00049 #ifdef __QNXNTO__
00050   #define USE_BIN "/usr/bin/use"
00051 #else
00052   #define USE_BIN "/bin/use"
00053 #endif
00054 
00055 static char *makeofile(char *in, char *extension) {
00056   int i, lastslash, lastdot;
00057   char *out;
00058   
00059   lastslash = lastdot = -1;
00060   for (i = 0; in[i]; i++) {
00061         if (in[i] == '/') lastslash = i;
00062         else if (in[i] == '.') lastdot = i;
00063   }
00064   if (lastdot > lastslash) i = lastdot;
00065   i = i - lastslash - 1; /* length of basename minus extension */
00066   out = malloc(i+strlen(extension)+1);
00067   assert(out != NULL);
00068   strncpy(out, in+lastslash+1, i);
00069   strcpy(out+i, extension);
00070   return(out);
00071 }
00072 
00073 FILE *open_output_file(char *name) {
00074   FILE *fp;
00075   
00076   if (*name == '-') return(stdout);
00077   fp = fopen(name, "w");
00078   if (fp == NULL)
00079         nl_error(3, "Unable to open output file %s", name);
00080   return(fp);
00081 }
00082 
00083 static void compile_exit(void) {
00084   if (error_level > 0 && output_filename != NULL
00085           && !(compile_options & CO_KEEP_OUTPUT)) {
00086         if (ofile != NULL) fclose(ofile);
00087         remove(output_filename);
00088   }
00089 }
00090 
00091 int compile_error(int level, const char *format, ...) {
00092   va_list arg;
00093   
00094   if (level < -1 && nl_debug_level > level) return(level);
00095   if (level > error_level) error_level = level;
00096   if (error_level == 1 && (compile_options&CO_IGN_WARN))
00097         error_level = 0;
00098   va_start(arg, format);
00099   if (input_linenumber > 0) {
00100         if (input_filename != NULL)
00101           fprintf(stderr, "%s %d:", input_filename, input_linenumber);
00102         else fprintf(stderr, "%d:", input_linenumber);
00103   }
00104   nl_verror(stderr, level, format, arg);
00105   va_end(arg);
00106   return(level);
00107 }
00108 
00109 int yywrap(void) {
00110   input_linenumber = 0;
00111   if (input_filename != NULL) fclose(yyin);
00112   /* I could free the old filename here, but I think I will leave
00113      it allocated to allow the filename to be saved for debugging. */
00114   input_filename = llos_deq(&input_files);
00115   if (input_filename == 0) return(1);
00116   if (input_filename[0] == '-')
00117         compile_error(3, "Misplaced option %s", input_filename);
00118   yyin = open_input_file(input_filename);
00119   if (yyin == NULL)
00120         compile_error(3, "Unable to open input file %s", input_filename);
00121   input_linenumber = 1;
00122   return(0);
00123 }
00124 
00125 void compile_init_options(int argc, char **argv, char *extension) {
00126   int c;
00127 
00128   opterr = 0;
00129   optind = OPTIND_RESET;  
00130   while ((c = getopt(argc, argv, opt_string)) != -1) {
00131         switch (c) {
00132           case 'q':
00133             execl( USE_BIN, USE_BIN, argv[0], NULL );
00134                 compile_error(4, "Unable to exec use" );
00135                 exit(1);
00136           case 'w': compile_options &= ~CO_IGN_WARN; break;
00137           case 'k': compile_options |= CO_KEEP_OUTPUT; break;
00138           case 'v':
00139                 nl_debug_level--;
00140                 break;
00141           case 'o':
00142                 output_filename = optarg;
00143                 ofile = open_output_file(output_filename);
00144                 break;
00145         }
00146   }
00147   atexit(compile_exit);
00148 
00149   /* enqueue the input file names */
00150   for (c = optind; c < argc; c++)
00151         llos_enq(&input_files, argv[c]);
00152 
00153   /* open the first input file */
00154   if (yywrap())
00155         compile_error(3, "No input file specified");
00156 
00157   if (ofile == NULL && input_filename != NULL) {
00158         output_filename = makeofile(input_filename, extension);
00159         ofile = open_output_file(output_filename);
00160   }
00161 }
00162 /*
00163 =Name open_output_file(): Compiler support function
00164 =Subject Compiler
00165 =Synopsis
00166 
00167 #include <stdio.h>
00168 #include "compiler.h"
00169 FILE *open_output_file(char *name);
00170 
00171 =Description
00172 
00173   Performs standard operations to open a compiler output file.
00174 
00175 =Returns
00176 
00177   Output file pointer.
00178 
00179 =SeeAlso
00180   =Compiler= functions.
00181 =End
00182 
00183 =Name yywrap(): Process multiple input files
00184 =Subject Compiler
00185 =Synopsis
00186 
00187 #include <stdio.h>
00188 #include "compiler.h"
00189 int yywrap(void);
00190 
00191 =Description
00192 
00193   This is a redefinition of the default yacc yywrap() function in
00194   order to support processing of multiple input files as one.
00195 
00196 =Returns
00197 =SeeAlso
00198   =Compiler= functions.
00199 =End
00200 
00201 =Name compile_init_options(): Command line arguments for compilers
00202 =Subject Compiler
00203 =Subject Startup
00204 =Synopsis
00205 
00206 #include <stdio.h>
00207 #include "compiler.h"
00208 void compile_init_options(int argc, char **argv, char *extension);
00209 
00210 =Description
00211 
00212   Handles command line arguments for compilers, specifically:
00213   
00214   <UL>
00215   <LI>-q: Print the compiler's usage message
00216   <LI>-w: Treat warnings as errors
00217   <LI>-k: Do not delete the output file if there are errors
00218   <LI>-v: Add another level of debugging
00219   <LI>-o file: Write output to file
00220   </UL>
00221 
00222 =Returns
00223 
00224   Nothing.
00225 
00226 =SeeAlso
00227   =Compiler= functions.
00228 =End
00229 
00230 =Name compile_error(): nl_error function for compilers
00231 =Subject Compiler
00232 =Synopsis
00233 #include <stdio.h>
00234 #include "compiler.h"
00235 int compile_error(int level, char *format, ...);
00236 
00237 =Description
00238 =Returns
00239 =SeeAlso
00240   =Compiler= functions.
00241 =End
00242 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines