/* Read environment from env and make it our own keeping the env variables in * keep_env if they're present in the current environment. * The environment file must exist, may be empty, and is expected to be of the format: * key=value\0key=value\0... */ static void load_env(const char *env, const char **keep_env) { struct stat st; char *map, *k, *v; typeof(st.st_size) i; append_env(env, keep_env); map_file(env, PROT_READ|PROT_WRITE, MAP_PRIVATE, &st, (void **)&map); pexit_if(clearenv() != 0, "Unable to clear environment"); if(!st.st_size) return; map[st.st_size - 1] = '\0'; /* ensure the mapping is null-terminated */ for(i = 0; i < st.st_size;) { k = &map[i]; i += strlen(k) + 1; exit_if((v = strchr(k, '=')) == NULL, "Malformed environment entry: \"%s\"", k); /* a private writable map is used permitting s/=/\0/ */ *v = '\0'; v++; pexit_if(setenv(k, v, 1) == -1, "Unable to set env variable: \"%s\"=\"%s\"", k, v); } }
int main( int argc, char *argv[]) { char *fnames[32]; int nr_files = 0; FILE *obj = NULL; TEXT_RLD tr; char *objname = NULL; char *lstname = NULL; int arg; int i; STACK stack; int errcount; if (argc <= 1) { print_help(); exit(EXIT_FAILURE); } for (arg = 1; arg < argc; arg++) if (*argv[arg] == '-') { char *cp; cp = argv[arg] + 1; if (!stricmp(cp, "h")) { print_help(); } else if (!stricmp(cp, "v")) { print_version(stderr); } else if (!stricmp(cp, "e")) { /* Followed by options to enable */ /* Since /SHOW and /ENABL option names don't overlap, I consolidate. */ if(arg >= argc-1 || !isalpha((unsigned char)*argv[arg+1])) { usage("-e must be followed by an option to enable\n"); } upcase(argv[++arg]); enable_tf(argv[arg], 1); } else if (!stricmp(cp, "d")) { /* Followed by an option to disable */ if(arg >= argc-1 || !isalpha((unsigned char)*argv[arg+1])) { usage("-d must be followed by an option to disable\n"); } upcase(argv[++arg]); enable_tf(argv[arg], 0); } else if (!stricmp(cp, "m")) { /* Macro library */ /* This option gives the name of an RT-11 compatible macro library from which .MCALLed macros can be found. */ if(arg >= argc-1 || *argv[arg+1] == '-') { usage("-m must be followed by a macro library file name\n"); } arg++; int allow_olb = strcmp(argv[argc-1], "-x") == 0; mlbs[nr_mlbs] = mlb_open(argv[arg], allow_olb); if (mlbs[nr_mlbs] == NULL) { fprintf(stderr, "Unable to register macro library %s\n", argv[arg]); exit(EXIT_FAILURE); } nr_mlbs++; } else if (!stricmp(cp, "p")) { /* P for search path */ /* The -p option gives the name of a directory in which .MCALLed macros may be found. */ { if(arg >= argc-1 || *argv[arg+1] == '-') { usage("-p must be followed by a macro search directory\n"); } append_env("MCALL", argv[arg+1]); arg++; } } else if (!stricmp(cp, "I")) { /* I for include path */ /* The -I option gives the name of a directory in which .included files may be found. */ { if(arg >= argc-1 || *argv[arg+1] == '-') { usage("-I must be followed by a include file search directory\n"); } append_env("INCLUDE", argv[arg+1]); arg++; } } else if (!stricmp(cp, "o")) { /* The -o option gives the object file name (.OBJ) */ if(arg >= argc-1 || *argv[arg+1] == '-') { usage("-o must be followed by the object file name\n"); } ++arg; objname = argv[arg]; } else if (!stricmp(cp, "l")) { /* The option -l gives the listing file name (.LST) */ /* -l - enables listing to stdout. */ if(arg >= argc-1 || (argv[arg+1][0] == '-' && argv[arg+1][1] != '\0')) { usage("-l must be followed by the listing file name (- for standard output)\n"); } lstname = argv[++arg]; if (strcmp(lstname, "-") == 0) lstfile = stdout; else lstfile = fopen(lstname, "w"); } else if (!stricmp(cp, "x")) { /* The -x option invokes macro11 to expand the contents of the registered macro libraries (see -m) into individual .MAC files in the current directory. No assembly of input is done. This must be the last command line option. */ int m; if(arg != argc-1) { usage("-x must be the last option\n"); } for (m = 0; m < nr_mlbs; m++) mlb_extract(mlbs[m]); return EXIT_SUCCESS; } else if (!stricmp(cp, "ysl")) { /* set symbol_len */ if (arg >= argc-1) { usage("-s must be followed by a number\n"); } else { char *s = argv[++arg]; char *endp; int sl = strtol(s, &endp, 10); if (*endp || sl < SYMMAX_DEFAULT || sl > SYMMAX_MAX) { usage("-s must be followed by a number\n"); } symbol_len = sl; } } else if (!stricmp(cp, "yus")) { /* allow underscores */ symbol_allow_underscores = 1; } else if (!stricmp(cp, "yl1")) { /* list the first pass, in addition to the second */ list_pass_0++; } else if (!stricmp(cp, "yd")) { enabl_debug++; } else { fprintf(stderr, "Unknown option %s\n", argv[arg]); print_help(); exit(EXIT_FAILURE); } } else { fnames[nr_files++] = argv[arg]; } if (objname) { obj = fopen(objname, "wb"); if (obj == NULL) return EXIT_FAILURE; } add_symbols(&blank_section); text_init(&tr, NULL, 0); module_name = memcheck(strdup(".MAIN.")); xfer_address = new_ex_lit(1); /* The undefined transfer address */ stack_init(&stack); /* Push the files onto the input stream in reverse order */ for (i = nr_files - 1; i >= 0; --i) { STREAM *str = new_file_stream(fnames[i]); if (str == NULL) { report(NULL, "Unable to open file %s\n", fnames[i]); exit(EXIT_FAILURE); } stack_push(&stack, str); } DOT = 0; current_pc->section = &blank_section; last_dot_section = NULL; pass = 0; stmtno = 0; lsb = 0; next_lsb = 1; lsb_used = 0; last_macro_lsb = -1; last_locsym = 32767; last_cond = -1; sect_sp = -1; suppressed = 0; assemble_stack(&stack, &tr); if (list_pass_0 && lstfile) { list_symbol_table(); } #if 0 if (enabl_debug > 1) dump_all_macros(); #endif assert(stack.top == NULL); migrate_implicit(); /* Migrate the implicit globals */ write_globals(obj); /* Write the global symbol dictionary */ #if 0 sym_hist(&symbol_st, "symbol_st"); /* Draw a symbol table histogram */ #endif text_init(&tr, obj, 0); stack_init(&stack); /* Superfluous... */ /* Re-push the files onto the input stream in reverse order */ for (i = nr_files - 1; i >= 0; --i) { STREAM *str = new_file_stream(fnames[i]); if (str == NULL) { report(NULL, "Unable to open file %s\n", fnames[i]); exit(EXIT_FAILURE); } stack_push(&stack, str); } DOT = 0; current_pc->section = &blank_section; last_dot_section = NULL; pass = 1; stmtno = 0; lsb = 0; next_lsb = 1; lsb_used = 0; last_macro_lsb = -1; last_locsym = 32767; pop_cond(-1); sect_sp = -1; suppressed = 0; errcount = assemble_stack(&stack, &tr); text_flush(&tr); while (last_cond >= 0) { report(NULL, "%s:%d: Unterminated conditional\n", conds[last_cond].file, conds[last_cond].line); pop_cond(last_cond - 1); errcount++; } for (i = 0; i < nr_mlbs; i++) mlb_close(mlbs[i]); write_endmod(obj); if (obj != NULL) fclose(obj); if (errcount > 0) fprintf(stderr, "%d Errors\n", errcount); if (lstfile) { list_symbol_table(); } if (lstfile && strcmp(lstname, "-") != 0) fclose(lstfile); return errcount > 0 ? EXIT_FAILURE : EXIT_SUCCESS; }