ARPDAS_QNX6 1.0
|
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 */