int process_file(char *filename) { struct stat st; stat(filename, &st); if (!st.st_size) return 1; uint8_t *file_buf = (uint8_t *)malloc(st.st_size); if (!file_buf) return 1; FILE *fp = fopen(filename, "r"); if (!fp) { free(file_buf); return 1; } size_t len = fread(file_buf, sizeof(char), st.st_size, fp); if (!len) { printf("%s couldn't be read.\n", filename); free(file_buf); return 1; } syntax_check(file_buf); semantic_analyze(file_buf); }
// compile a single C source file int do_c_compile(uint8_t *fname) { // open the source file (as text, for reading) int in = qcc_open_r ((char *) fname, 0); if (in < 0) return QCC_ERR_FNOTFOUND; // XXX: get a source file version number and timestamp, to include as extra info in the object file preprocess (in, fname); // preprocessing: includes, macros, #ifs, etc. // if (tccg_output_type == TCC_OUTPUT_PREPROCESS) // dump_cpp_output(); // return 0; tokenize(); // take the messy output from the preprocessor and tokenize it prettily prototypes(); // parse funct/struct/union/enum/typedef info at global scope syntax_check(); // hopefully a complete and final check on syntax, one function at a time? if (total_errs != 0) return 1; // expression_simplification(); -- do dead code elimination // tcg_frontend_conversion(); -- convert tokens into a superset of TCG frontend code // Note: tcg can only handle function returns in a single register, // but the C99 spec requires (??) functions to be able to return complete structs, long doubles, 64bit values, etc. // so this frontend conversion cannot be to pure tcg, I don't think -- unless there is a clever workaround for the return value thing. // XXX: -- some function needs to build the symtable/bss/data/rodata mem buffers? // emit_to_target needs to look up symbols -- what format of symbol is nicest for that? // this next function is a generic entrypoint for the config-selected specific target CPU emit_to_target(); // convert to binary -- create the .text mem buffer // XXX: then need a function that packs these mem buffers at the upper end of the workspace and lowers wrk_rem // (and stores info about where all of it is located, of course) return 0; }
/* execution for the shell */ int execute() { /* e.g. "ls -l | cat -n" */ char line[MAX_LINE_LEN]; /* e.g. "ls -l", "cat -n" */ char cmd[MAX_CMD][MAX_CMD_LEN]; /* e.g. "ls", "-l" */ char buf[MAX_ARGC][MAX_ARG_LEN]; int status; /* background flag */ int is_bg; char str[2]; int i, n; /* processes to be waited */ pid_t wpid[MAX_CMD]; int cmd_num; COMMAND command; is_bg = 0; /* handle child processes exit signal and ctrl-c signal */ if (signal(SIGCHLD, chldHandler) == SIG_ERR || signal(SIGINT, intHandler) == SIG_ERR) { perror("Signal() error"); return DEFAULT_STATUS; } if (cflag) { if ((n = syntax_check(ccmd, &is_bg)) == -1) { fprintf(stderr, "sish: %s: Syntax error\n", ccmd); return DEFAULT_STATUS; } else if (n == 0) return EXIT_SUCCESS; cmd_num = command_parser(ccmd, cmd); if (xflag) { trace(cmd, cmd_num); } /* exit and cd */ if (cmd_num == 1) { command_init(&command); argument_parser(cmd[0], buf, &command); if (strcmp(command.arg[0], "exit") == 0) { if (exit_syntax_check(command.arg) == -1) { exit_usage(); ret_val = EXIT_FAILURE; return ret_val; } else { return ret_val; } } else if (strcmp(command.arg[0], "cd") == 0) { if (cd_syntax_check(command.arg) == -1) { cd_usage(); ret_val = EXIT_FAILURE; return ret_val; } ret_val = cd_exec(command.arg); return ret_val; } } execute_command(cmd, wpid, cmd_num); if (!is_bg) { for (i = 0; i < cmd_num; i++) { if (waitpid(wpid[i], &status, 0) == -1) { if (errno == ECHILD) { errno = 0; continue; } fprintf(stderr, "%d: waitpid() error" ": %s\n", wpid[i], strerror(errno)); return ret_val; } ret_val = check_status(status); } } return ret_val; } for (;;) { LBEGIN: print(); i = 0; while ((n = read(STDIN_FILENO, str, 1)) > 0) { str[1] = '\0'; if (strcmp(str, "\n") == 0) { line[i] = '\0'; break; } if (i >= MAX_LINE_LEN - 1) { fprintf(stderr, "sish: commands too long\n"); ret_val = EXIT_FAILURE; goto LBEGIN; } line[i] = str[0]; i++; } if (n < 0) { fprintf(stderr, "sish: read() error: %s\n", strerror(errno)); ret_val = EXIT_FAILURE; continue; } if ((n = syntax_check(line, &is_bg)) == -1) { fprintf(stderr, "sish: %s: Syntax error\n", line); ret_val = DEFAULT_STATUS; continue; } else if (n == 0) { continue; } cmd_num = command_parser(line, cmd); if (xflag) { trace(cmd, cmd_num); } /* exit and cd */ if (cmd_num == 1) { command_init(&command); argument_parser(cmd[0], buf, &command); if (strcmp(command.arg[0], "exit") == 0) { if (exit_syntax_check(command.arg) == -1) { exit_usage(); ret_val = EXIT_FAILURE; continue; } else { break; } } else if (strcmp(command.arg[0], "cd") == 0) { if (cd_syntax_check(command.arg) == -1) { cd_usage(); ret_val = EXIT_FAILURE; continue; } ret_val = cd_exec(command.arg); continue; } } execute_command(cmd, wpid, cmd_num); if (!is_bg) { for (i = 0; i < cmd_num; i++) { if (waitpid(wpid[i], &status, 0) == -1) { if (errno == ECHILD) { errno = 0; continue; } fprintf(stderr, "%d: waitpid() error" ": %s\n", wpid[i], strerror(errno)); return ret_val; } ret_val = check_status(status); } } } return ret_val; }