/* If the path has the home directory in it, replace it with a tilde. */ int tilde_expand(char *buf, int buf_size, const char *path1) { char path[MAX_FILENAME_SIZE]; char *homedir; int ret = 0; if (!is_abs_path(path1)) { if (*path1 == '~') { if (path1[1] == '\0' || path1[1] == '/') { homedir = getenv("HOME"); if (homedir) { pstrcpy(path, sizeof(path), homedir); #ifdef CONFIG_WIN32 path_win_to_unix(path); #endif remove_slash(path); pstrcat(path, sizeof(path), path1 + 1); path1 = path; } } else { /* CG: should get info from getpwnam */ pstrcpy(path, sizeof(path), "/home/"); pstrcat(path, sizeof(path), path1 + 1); path1 = path; } ret = 1; } } pstrcpy(buf, buf_size, path1); return ret; }
/* canonize the path and make it absolute */ void canonize_absolute_path(char *buf, int buf_size, const char *path1) { char cwd[MAX_FILENAME_SIZE]; char path[MAX_FILENAME_SIZE]; char *homedir; if (!is_abs_path(path1)) { /* XXX: should call it again */ if (*path1 == '~' && (path1[1] == '\0' || path1[1] == '/')) { homedir = getenv("HOME"); if (homedir) { pstrcpy(path, sizeof(path), homedir); pstrcat(path, sizeof(path), path1 + 1); goto next; } } /* CG: not sufficient for windows drives */ getcwd(cwd, sizeof(cwd)); #ifdef WIN32 path_win_to_unix(cwd); #endif makepath(path, sizeof(path), cwd, path1); } else { pstrcpy(path, sizeof(path), path1); } next: canonize_path(buf, buf_size, path); }
/* canonize the path and make it absolute */ void canonize_absolute_path_old(char *buf, int buf_size, const char *path1) { char path[1024]; if (!is_abs_path(path1)) { /* XXX: should call it again */ getcwd(path, sizeof(path)); #ifdef WIN32 path_win_to_unix(path); #endif pstrcat(path, sizeof(path), "/"); pstrcat(path, sizeof(path), path1); } else { pstrcpy(path, sizeof(path), path1); } canonize_path(buf, buf_size, path); }
/* canonize the path and make it absolute */ void canonize_absolute_path(char *buf, int buf_size, const char *path1) { char cwd[MAX_FILENAME_SIZE]; char path[MAX_FILENAME_SIZE]; if (is_abs_path(path1)) { pstrcpy(path, sizeof(path), path1); } else { /* CG: not sufficient for windows drives */ if (!expand_unix_home(path1, path, sizeof(path))) { getcwd(cwd, sizeof(cwd)); path_win_to_unix(cwd); makepath(path, sizeof(path), cwd, path1); } } canonize_path(buf, buf_size, path); }
/* canonicalize the path and make it absolute */ void canonize_absolute_path(char *buf, int buf_size, const char *path1) { char cwd[MAX_FILENAME_SIZE]; char path[MAX_FILENAME_SIZE]; if (!is_abs_path(path1)) { if (*path1 == '~') { tilde_expand(path, MAX_FILENAME_SIZE, path1); path1 = path; } else { /* CG: not sufficient for windows drives */ /* CG: should test result */ getcwd(cwd, sizeof(cwd)); #ifdef CONFIG_WIN32 path_win_to_unix(cwd); #endif makepath(path, sizeof(path), cwd, path1); path1 = path; } } canonize_path(buf, buf_size, path1); }
int wisvc_Handle_I_and_J_options (int argc, char **argv, char *s, int i, int autostart) { int called_as_service = 0; size_t path_len; int start_now = 0; char *service_name = (*(s + 2) ? (s + 2) : WISVC_DEFAULT_SERVICE_NAME); char *progname = argv[0]; char *last_of_path, *cutpnt; char BinaryPathName[(MAX_BINARY_PATH) + 10]; /* if(i > 1) { err_printf(( "%s: If you give %s option, it MUST be the first argument on command line!", progname,s)); kubl_main_exit(1); } */ /* Then construct absolute path to this binary executable by combining working directory path got with getcwd with the program name got from argv[0]. Note that the program name itself can be relative or absolute path. getcwd returns a string that represents the path of the current working directory. If the current working directory is the root, the string ends with a backslash (\). If the current working directory is a directory other than the root, the string ends with the directory name and not with a backslash. Note that absolute paths with upward parts (..) like the one below seem to work equally well, so we do not need to worry about .. :s and .:s in any special way. D:\inetpub\wwwroot\..\..\ic\.\diskit\wi\windebug\wi.exe */ if (is_abs_path (progname)) { strncpy (BinaryPathName, progname, (MAX_BINARY_PATH)); } else /* We have to combine pwd + relative starting path */ { if (NULL == getcwd (BinaryPathName, _MAX_PATH)) { err_printf (("%s: Cannot getcwd because: %s", progname, strerror (errno))); exit (1); } path_len = strlen (BinaryPathName); last_of_path = (BinaryPathName + path_len - 1); if ((0 == path_len) || !is_abs_path (last_of_path)) { /* Add the missing path separator between if needed */ strncat_ck (BinaryPathName, "\\", (MAX_BINARY_PATH)); } /* And then the progname itself. */ strncat_ck (BinaryPathName, progname, (MAX_BINARY_PATH)); } /* Add our own special .eXe extension to the program name, so that when service is started, the code in main can see from argv[0] that it was started as a service, not as an ordinary command line program. */ strncat_ck (BinaryPathName, WISVC_EXE_EXTENSION_FOR_SERVICE, (MAX_BINARY_PATH)); /* Do chdir to the same directory where the executable is, needed because of wi.cfg check soon performed. */ if ((NULL != (cutpnt = strrchr (BinaryPathName, '\\')))) { /* Search the last backslash. */ unsigned char save_the_following_char = *(((unsigned char *) cutpnt) + 1); *(cutpnt + 1) = '\0'; if (chdir (BinaryPathName)) /* Is not zero, i.e. -1, an error. */ { /* However, we do not exit yet. */ err_printf (("%s: Cannot chdir to \"%s\" because: %s", argv[0], BinaryPathName, strerror (errno))); exit (1); } *(((unsigned char *) cutpnt) + 1) = save_the_following_char; } /* Add all command line arguments after the absolute program name itself, separated by spaces. The started service will see them in the elements of argv vector, in the normal way, that is argv[0] will contain just the absolute program name which ends with .eXe and arguments are in argv[1], argv[2], etc. Check also for options -S (start the service), and -W change working directory. The latter would not be actually necessary to do here, but, if the directory is invalid, then it is much more friendly to give an error message here, than let the service itself fail, and hide the same error message to god knows which log file. Check that the user does not try to give options -D, -U, -R or -d to the service to be installed. */ for (i = 1; i < argc; i++) { s = argv[i]; if ('-' == s[0]) { switch (s[1]) { /* With -S ignore the possibility that a different service name could be specified after it than after -I or -J DON'T ADD OPTIONS -S, -I or -J to BinaryPathName, as they would be ignored anyway in service. */ case 'S': { start_now = 1; continue; } case 'I': case 'J': { continue; } case 'W': { int stat = wisvc_Handle_W_option (argc, argv, s, &i, called_as_service); if (stat) { kubl_main_exit (stat); } break; } case 'D': case 'U': /* case 'R': */ case 'd': { err_printf (( "%s: Sorry, the option %s can be used only from command line, not in service!\n", argv[0], s)); exit (1); } } } strncat_ck (BinaryPathName, " ", (MAX_BINARY_PATH)); strncat_ck (BinaryPathName, argv[i], (MAX_BINARY_PATH)); } { /* Check already HERE that there is a config file in the final working directory, for the same user-friendly reason as checking the validity of -W option's argument. */ int fd = open (CFG_FILE, O_RDWR); if (fd < 0) { err_printf (( "There must be a %s file in the server's working directory. Exiting.\n", CFG_FILE)); exit (-1); } fd_close (fd, NULL); /* Defined in widisk.h */ } wisvc_CreateKublService (argc, argv, service_name, BinaryPathName, autostart, start_now); return (0); }
char *handle_directive (const char *ptr) { static const char *dirs[] = {"db", "dw", "end", "org", "byte", "word", "fill", "block", "addinstr", "echo", "error", "list", "nolist", "equ", "show", "option", "seek", "assume", "dl", "long", NULL}; char name_buf[32]; int dir; //same deal as handle_preop, just with directives instead bool valid_directive = false; unsigned name_len = 0; while (ptr[name_len] != 0 && !isspace(ptr[name_len])) { name_len++; } // If longer than name_buf, it can't be a valid directive. if (name_len < sizeof(name_buf)) { // Copy string for comparing against memcpy(name_buf, ptr, name_len); name_buf[name_len] = 0; dir = 0; while (dirs[dir]) { if (!strcasecmp(dirs[dir], name_buf)) { valid_directive = true; break; } dir++; } } if (!valid_directive) return handle_opcode_or_macro ((char *) ptr - 1); ptr = skip_whitespace(&ptr[name_len]); switch (dir) { case 0: //DB case 4: //BYTE { ptr = parse_emit_string (ptr, ES_BYTE, NULL); break; } case 1: //DW case 5: //WORD { ptr = parse_emit_string (ptr, ES_WORD, NULL); break; } case 18: //DL case 19: //LONG { ptr = parse_emit_string (ptr, ES_LONG, NULL); break; } case 3: //ORG { int value; char value_str[256] = ""; bool fResult = read_expr(&ptr, value_str, ""); if (fResult == true) { if (parse_num(value_str, &value) == true) { if (value < 0) { SetLastSPASMError(SPASM_ERR_INVALID_ADDRESS, skip_whitespace(value_str)); } else { program_counter = value; } } } if ((fResult == false) || (strlen(skip_whitespace(value_str)) == 0)) { SetLastSPASMError(SPASM_ERR_VALUE_EXPECTED); } break; } case 6: //FILL case 7: //BLOCK { int size, fill_value; char szSize[256], szFill[256]; bool old_listing_on = listing_on; //listing_on = false; read_expr (&ptr, szSize, ","); parse_num (szSize, &size); ptr = skip_whitespace (ptr); if (*ptr == ',') ptr++; if (read_expr (&ptr, szFill, "")) { //if there's a value to fill the block with, then handle that parse_num (szFill, &fill_value); } else { //otherwise use 0 fill_value = 0; } if (size < 0) { SetLastSPASMError(SPASM_ERR_SIZE_MUST_BE_POSITIVE, szSize); listing_on = old_listing_on; break; } if (fill_value < -128 || fill_value > 255) { SetLastSPASMWarning(SPASM_WARN_TRUNCATING_8); } program_counter += size; stats_datasize += size; while (size-- > 0) write_out (fill_value & 0xFF); //listing_on = old_listing_on; break; } case 8: //ADDINSTR { instr *instr = (struct _instr *) malloc (sizeof (struct _instr)); char word[256]; int result; char *mnemonic; size_t i, base = 0, size_left; int j; opcode *last_opcode = NULL, *curr_opcode = all_opcodes, *new_opcode; memset (instr, 0, sizeof (struct _instr)); // Mnemonic if (!read_expr (&ptr, word, " \t")) goto addinstr_fail; mnemonic = strdup (word); // Args if (!read_expr (&ptr, word, " \t")) goto addinstr_fail; reduce_string (word); instr->args = strdup (word); // Instruction data if (!read_expr (&ptr, word, " \t")) goto addinstr_fail; conv_hex (word, word + strlen (word), &result); instr->instr_size = strlen (word) / 2; for (j = instr->instr_size - 1; j >= 0; j--) instr->instr_data[instr->instr_size - j - 1] = (result >> (j * 8)) & 0xFF; // Size if (!read_expr (&ptr, word, " \t")) goto addinstr_fail; if (!parse_num (word, &instr->size)) goto addinstr_fail; // Class read_expr (&ptr, word, " \t"); // Extended read_expr (&ptr, word, " \t"); // End data ... if (read_expr (&ptr, word, " \t")) { int output; conv_hex (word, word + strlen (word), &output); instr->end_data = (unsigned char) output; instr->has_end_data = true; } size_left = instr->size - instr->instr_size; while ((i = strcspn (&instr->args[base], "*")) + base != strlen (instr->args)) { switch (size_left - instr->has_end_data) { case 2: ((char *) instr->args)[base+i] = '*'; break; case 1: ((char *) instr->args)[base+i] = '&'; break; default: ((char *) instr->args)[base+i] = '&'; break; //show_error ("Invalid wildcard type in ADDRINSTR"); //goto addinstr_fail; break; } size_left -= 2; base += i + 1; } new_opcode = (opcode *) malloc (sizeof (opcode)); new_opcode->name = mnemonic; new_opcode->num_instrs = 1; new_opcode->use_count = 0; new_opcode->instrs = instr; new_opcode->is_added = true; while (curr_opcode) { if (strcasecmp (mnemonic, curr_opcode->name) == 0) break; last_opcode = curr_opcode; curr_opcode = curr_opcode->next; } if (curr_opcode == NULL) { last_opcode->next = new_opcode; new_opcode->next = NULL; } else { new_opcode->next = curr_opcode; if (last_opcode) last_opcode->next = new_opcode; else all_opcodes = new_opcode; } // You can ignore class, etc ptr = skip_to_line_end (ptr); break; addinstr_fail: SetLastSPASMError(SPASM_ERR_INVALID_ADDINSTR); if (instr && instr->args) free ((void *) instr->args); if (instr) free (instr); ptr = skip_to_line_end(ptr); break; } case 9: //ECHO { if (ptr[0] == '>') { char target_format[2] = "w"; FILE *echo_target; char filename[MAX_PATH]; char temp_filename[MAX_PATH]; define_t *define; if ((++ptr)[0] == '>') target_format[0] = 'a'; ptr = skip_whitespace (ptr + 1); if (is_end_of_code_line (ptr)) { SetLastSPASMError(SPASM_ERR_FILENAME_EXPECTED); return NULL; } read_expr (&ptr, filename, " \t"); // Is the filename given a macro? if ((define = search_defines (filename))) strncpy (filename, skip_whitespace(define->contents), sizeof (filename)); reduce_string(filename); if (is_abs_path(filename)) { strncpy(temp_filename, skip_whitespace (filename), sizeof (temp_filename)); } else { strncpy(temp_filename, temp_path, sizeof (temp_filename)); strncat(temp_filename, "/", sizeof (temp_filename) - 1); strncat(temp_filename, skip_whitespace (filename), sizeof (temp_filename) - 1); } echo_target = fopen (fix_filename (temp_filename), target_format); if (echo_target == NULL) { SetLastSPASMError(SPASM_ERR_NO_ACCESS, filename); return NULL; } //if the output's redirected to a file, process it now WORD orig_attributes = save_console_attributes(); set_console_attributes (COLOR_GREEN); ptr = parse_emit_string (ptr, ES_ECHO, echo_target); restore_console_attributes(orig_attributes); } else { char expr[256]; read_expr (&ptr, expr, ""); // If it craps out for some reason, save it for the next pass int session = StartSPASMErrorSession(); parse_emit_string (expr, ES_ECHO, NULL); if (IsSPASMErrorSessionFatal(session) == true) { add_pass_two_output (expr, OUTPUT_ECHO); } else if (GetSPASMErrorSessionErrorCount(session) > 0) { WORD orig_attributes = save_console_attributes(); set_console_attributes(COLOR_GREEN); int internal_session = StartSPASMErrorSession(); parse_emit_string (expr, ES_ECHO, stdout); restore_console_attributes(orig_attributes); EndSPASMErrorSession(internal_session); ReplaySPASMErrorSession(session); } else { expand_buf_t *echo = eb_init(256); parse_emit_string (expr, ES_FCREATE, echo); char *echo_string = eb_extract(echo); eb_free(echo); char *expanded_string = escape_string(echo_string); free(echo_string); add_pass_two_output (expanded_string, OUTPUT_ECHO); free(expanded_string); } EndSPASMErrorSession(session); } break; } case 10: //ERROR { expand_buf_t *eb = eb_init(64); ptr = parse_emit_string(ptr, ES_FCREATE, eb); char *error_str = eb_extract(eb); eb_free(eb); SetLastSPASMError(SPASM_ERR_CUSTOM, error_str); free(error_str); break; } case 11: //LIST { //if listing was off already, then the listing // for the start of this line wouldn't have been // written, so make sure the end doesn't get // written either if (!listing_on) listing_for_line_done = true; listing_on = true; break; } case 12: //NOLIST { //if listing is on, then it would've written // the starting stuff for this line already, // so take that out if ((mode & MODE_LIST) && listing_on) listing_offset -= 14; listing_on = false; break; } case 13: //EQU { // Finally, a proper .equ! int value; char value_str[256]; read_expr (&ptr, value_str, ""); if (!parse_num (value_str, &value) && parser_forward_ref_err) { } else { if (last_label == NULL) SetLastSPASMError(SPASM_ERR_EQUATE_MISSING_LABEL); else last_label->value = value; } break; } case 14: //SHOW { char name[256]; define_t *define; //get the name read_expr (&ptr, name, ""); define = search_defines (name); if (define == NULL) { //if it doesn't exist yet, save it for the second pass add_pass_two_output (name, OUTPUT_SHOW); } else { //otherwise, show it now show_define (define); } break; } case 15: //OPTION { char *word = NULL; arg_context_t context = ARG_CONTEXT_INITIALIZER; while ((word = extract_arg_string(&ptr, &context)) != NULL) { char name[256], *expr = word; char *define_name; define_t *define; read_expr(&expr, name, "="); if (*expr == '=') { expr++; } if (!(isalpha(name[0]))) { SetLastSPASMError(SPASM_ERR_INVALID_OPTION, name); return (char *) ptr; } if (is_end_of_code_line (skip_whitespace (expr))) expr = strdup ("1"); else { //if (!parse_num (expr, NULL)) // return NULL; expr = strdup (expr); } if (strlen (name) == 0) { show_error ("Invalid option statement"); return NULL; } define_name = (char *) malloc (strlen (name) + 3); strcat (strcpy (define_name, "__"), name); define = add_define (define_name, NULL); set_define (define, expr, -1, false); free(expr); } break; } case 16: //SEEK { int value; char value_str[256]; read_expr (&ptr, value_str, ""); parse_num (value_str, (int *) &value); //printf("value_str: %s\npc: %d\n", value_str, program_counter); if (value > program_counter && (value - program_counter > output_buf_size - (out_ptr - output_contents))) show_fatal_error ("Seek location %d out of bounds", value); else if (value < program_counter && (value - (int) program_counter + (out_ptr - output_contents) < 0)) show_fatal_error ("Seek value %d too small", value); out_ptr += value - ((int) program_counter); //printf("base: %p; ptr: %p\n", output_contents, out_ptr); program_counter = value; break; } case 17: //ASSUME { char args[256]; read_expr(&ptr, args, ""); char word[256]; char *value_str = args; read_expr(&value_str, word, "="); int value = 1; bool success = true; if (*value_str == '=') { success = parse_num(value_str+1, &value); } if (!(mode & MODE_EZ80) || strcasecmp(word, "adl") || !success) { SetLastSPASMError(SPASM_ERR_INVALID_OPTION, args); return (char *)ptr; } adl_mode = (value != 0); break; } } return (char *) ptr; }
int run_assembly() { #ifdef _WIN32 struct _timeb time_start, time_end; _ftime(&time_start); #else struct timeb time_start, time_end; ftime(&time_start); #endif exit_code = EXIT_NORMAL; /*extern int generic_map[256]; ZeroMemory(generic_map, 256);*/ program_counter = 0x0000; stats_codesize = stats_datasize = stats_mintime = stats_maxtime = 0; last_label = NULL; error_occurred = false; listing_offset = 0; listing_for_line_done = false; line_start = NULL; old_line_num = 0; in_macro = 0; line_num = 0; #ifdef USE_BUILTIN_FCREATE cur_buf = 0; #endif #ifdef USE_REUSABLES curr_reusable = 0; total_reusables = 0; #endif expr_list = NULL; expr_list_tail = NULL; output_list = NULL; output_list_tail = NULL; assert(curr_input_file != NULL); //read in the input file if (!(mode & MODE_COMMANDLINE)) input_contents = (char *) get_file_contents (curr_input_file); if (!input_contents) { puts ("Couldn't open input file"); return EXIT_FATAL_ERROR; } out_ptr = output_contents; //along with the listing buffer, if required if ((mode & MODE_LIST)) { listing_buf = eb_init (LISTING_BUF_SIZE); listing_offset = 0; listing_on = true; } //find the path of the input file if (is_abs_path(curr_input_file)) { int i; strcpy(temp_path, curr_input_file); for (i = strlen(temp_path) - 1; temp_path[i] != '\\' && temp_path[i] != '/' && i > 0; i--); if (i >= 0) temp_path[i] = '\0'; else strcpy(temp_path, "."); } else { #ifdef WIN32 _getcwd(temp_path, sizeof (temp_path)); #else getcwd(temp_path, sizeof (temp_path)); #endif } //add the the input file's path to the include directories include_dirs = list_prepend (include_dirs, strdup (temp_path)); printf ("Pass one... \n"); int first_pass_session = StartSPASMErrorSession(); run_first_pass ((char *) input_contents); ReplayFatalSPASMErrorSession(first_pass_session); EndSPASMErrorSession(first_pass_session); //free include dirs when done if ((mode & MODE_COMMANDLINE) == 0) { release_file_contents(input_contents); input_contents = NULL; } list_free (include_dirs, true, NULL); include_dirs = NULL; //...and if there's output, run the second pass and write it to the output file if (mode & MODE_SYMTABLE || mode & MODE_NORMAL || mode & MODE_LIST) { printf ("Pass two... \n"); int second_pass_session = StartSPASMErrorSession(); run_second_pass (); ReplaySPASMErrorSession(second_pass_session); EndSPASMErrorSession(second_pass_session); if (mode & MODE_SYMTABLE) { char* fileName = change_extension(output_filename, "lab"); write_labels (fileName); free(fileName); } //run the output through the appropriate program export and write it to a file if (mode & MODE_NORMAL && output_filename != NULL) { write_file (output_contents, out_ptr - output_contents, output_filename); } //write the listing file if necessary if ((mode & MODE_LIST)) { FILE *file; char *name; //get file name name = change_extension (output_filename, "lst"); file = fopen (name, "wb"); if (!file) { printf ("Couldn't open listing file '%s'", name); free (name); return EXIT_FATAL_ERROR; } free (name); if (fwrite (listing_buf->start, 1, listing_offset, file) != listing_offset) { puts ("Error writing to listing file"); fclose (file); return EXIT_FATAL_ERROR; } fclose (file); eb_free(listing_buf); listing_buf = NULL; } //free the output buffer and all the names of input files list_free(input_files, true, NULL); input_files = NULL; } //if there's info to be dumped, do that if (mode & MODE_CODE_COUNTER) { fprintf (stdout, "Size: %u\nMin. execution time: %u\nMax. execution time: %u\n", stats_codesize, stats_mintime, stats_maxtime); } if (mode & MODE_STATS) { fprintf(stdout, "Number of labels: %u\nNumber of defines: %u\nCode size: %u\nData size: %u\nTotal size: %u\n", get_num_labels (), get_num_defines (), stats_codesize, stats_datasize, stats_codesize + stats_datasize); } #ifdef _WIN32 _ftime(&time_end); #else ftime(&time_end); #endif int s_diff = (int) (time_end.time - time_start.time); int ms_diff = time_end.millitm - time_start.millitm; if (ms_diff < 0) { ms_diff += 1000; s_diff -= 1; } else if (ms_diff > 1000) { ms_diff -= 1000; s_diff += 1; } printf("Assembly time: %0.3f seconds\n", (float) s_diff + ((float) ms_diff / 1000.0f)); return exit_code; }