#define foobarbaz /* # A shell script within a source file. Ugly, but it works... TRGT='cbuild' for i in $@ ; do if [ "$i" = "--make-compiled" ] ; then echo "Compiling '$TRGT', please wait..." gcc -W -Wall -O2 -o $TRGT $0 exit $? fi done gcc -W -Wall -Werror -o /tmp/$TRGT "$0" && { "/tmp/$TRGT" `for i in $@ ; do echo "$i" ; done` ; RET=$? ; rm -f "/tmp/$TRGT" ; exit $RET ; } exit $? */ #include #include #include #include #include #include #include #include #include #ifdef _WIN32 static void setenv(const char *env, const char *val, int overwrite) { static char buf[128]; if(!overwrite && getenv(env)) return; snprintf(buf, sizeof(buf), "%s=%s", env, val); _putenv(buf); } static void unsetenv(const char *env) { setenv(env, "", 1); } #ifdef _MSC_VER #define strcasecmp stricmp #define strncasecmp strnicmp #define snprintf _snprintf #endif #endif /* Win32 */ #define INVOKE_BKP_SIZE 16 struct { FILE *f; char *bkp_lbuf; char *bkp_nextline; int bkp_line; int bkp_did_else; int bkp_did_cmds; int bkp_do_level; } invoke_backup[INVOKE_BKP_SIZE]; static struct stat statbuf; static char linebuf[64*1024]; static char buffer[64*1024]; static char *loaded_files; static char *sources; static char obj[64]; #define SRC_PATH_SIZE 32 static char *src_paths[SRC_PATH_SIZE]; /* getvar: Safely gets an environment variable, returning an empty string * instead of NULL */ static const char *getvar(const char *env) { const char *var; var = getenv(env); return (var?var:""); } /* find_src: Attempts to find the named sourcefile by searching the paths * listed in src_paths. It returns the passed string if the file exists as-is, * or if it couldn't be found. */ static char *find_src(char *src) { static char buf[64]; struct stat statbuf; int i; if(stat(src, &statbuf) == 0 || !src_paths[0]) return src; for(i = 0;src_paths[i] && i < SRC_PATH_SIZE;++i) { snprintf(buf, sizeof(buf), "%s/%s", src_paths[i], src); if(stat(buf, &statbuf) == 0) return buf; } return src; } /* check_obj_deps: Checks a file's dependancy list. The dependancy file is a * file expected to be in dep_dir and with the same name, but with a different * extension. The format of the file is simply: 'file.o: dependancies...' where * a '\' at the end of the line can be used as a next-line continuation. If the * dependancy file exists, none of the dependancies are missing, and none have * a modification time after 'obj_time', the function will return 0. Otherwise * 1 is returned denoting a rebuild may be required. */ static int check_obj_deps(char *src, time_t obj_time) { static char dep[64]; char *buf; int bufsize; struct stat statbuf; char *ptr = obj; FILE *df; size_t i; ptr = strrchr(src, '/'); if(!ptr) ptr = src; ptr = strrchr(ptr, '.'); if(ptr) *ptr = 0; snprintf(dep, sizeof(dep), "%s/%s%s", getvar("DEP_DIR"), src, getvar("DEP_EXT")); if(ptr) *ptr = '.'; df = fopen(dep, "r"); if(!df) { if(stat(src, &statbuf) != 0 || statbuf.st_mtime > obj_time) return 1; return 0; } fseek(df, 0, SEEK_END); bufsize = ftell(df)+1; buf = malloc(bufsize); if(!buf) { fclose(df); return 1; } fseek(df, 0, SEEK_SET); i = 0; while(fgets(buf+i, bufsize-i, df) != NULL) { i = strlen(buf); if(buf[i-1] != '\\') break; } fclose(df); ptr = strchr(buf, ':'); if(!ptr) { free(buf); return 1; } ++ptr; while(1) { char *stp; while(*ptr && isspace(*ptr)) { if(*ptr == '\n') { free(buf); return 0; } ++ptr; } if(!(*ptr)) { free(buf); return 0; } stp = ptr; while(*stp && !isspace(*stp)) { if(*stp == '\\') memmove(stp, stp+1, strlen(stp)); ++stp; } *(stp++) = 0; if(strcmp(ptr, "\n") != 0 && (stat(ptr, &statbuf) != 0 || statbuf.st_mtime > obj_time)) { free(buf); return 1; } ptr = stp; } } /* copy_file: Copies the source file 'sf' to 'df', preserving the source's * file mode and permissions, if possible. */ static int copy_file(const char *sf, const char *df) { struct stat statbuf; FILE *src, *dst; int ret, i; int fd; if(stat(sf, &statbuf) != 0) return 1; fd = open(df, O_WRONLY|O_TRUNC|O_CREAT, statbuf.st_mode); if(fd < 0) return 1; dst = fdopen(fd, "wb"); if(!dst) { close(fd); return 1; } src = fopen(sf, "rb"); if(!src) { fclose(dst); return 1; } ret = 0; do { i = fread(buffer, 1, sizeof(buffer), src); if(i > 0) i = fwrite(buffer, 1, i, dst); if(i < 0) ret = 1; } while(i > 0); fclose(src); fclose(dst); return ret; } /* extract_word: Extract a word starting at the string pointed to by 'str'. If * the word begins with a ' or " character, everything until that same * character will be considered part of the word. Otherwise, the word ends at * the first encountered whitespace. Returns the beginning of the next word, * or the end of the string. */ static char *extract_word(char **str) { char *end; char c; c = **str; if(c == '"' || c == '\'') { ++(*str); end = *str; while(*end) { if(*end == c) break; ++end; } } else { end = *str; while(!isspace(*end) && *end) ++end; } if(*end) *(end++) = 0; while(isspace(*end) && *end) ++end; return end; } /* build_obj_list: Builds a list of object files from the list of sources. If * any of the objects don't exist or have a modification time later than * 'base_time', the variable pointed to by 'do_link' will be set non-zero. */ static int build_obj_list(char *buffer, size_t bufsize, time_t base_time, int *do_link) { static char buf[64]; struct stat statbuf; char *next = sources; char *ptr; int i = 0; while(*(ptr=next)) { char *ext; char c = ' '; next = extract_word(&ptr); if(ptr > sources) { c = *(ptr-1); if(c != '"' && c != '\'') c = ' '; } ext = strrchr(ptr, '/'); if(!ext) ext = ptr; ext = strrchr(ext, '.'); if(ext) *ext = 0; snprintf(buf, sizeof(buf), "%s/%s%s", getvar("OBJ_DIR"), ptr, getvar("OBJ_EXT")); if(ext) *ext = '.'; if(!(*do_link) && (stat(buf, &statbuf) != 0 || base_time < statbuf.st_mtime)) *do_link = 1; i += snprintf(buffer+i, bufsize-i, " \"%s\"", buf); ptr += strlen(ptr); if(next > ptr) *ptr = c; } return i; } static int libify_name(char *buf, size_t buflen, char *name) { int i; char *curr = strrchr(name, '/'); if(curr) { *curr = 0; i = snprintf(buf, buflen, "%s/%s%s%s", name, getvar("LIB_PRE"), curr+1, getvar("LIB_EXT")); *curr = '/'; } else i = snprintf(buf, buflen, "%s%s%s", getvar("LIB_PRE"), name, getvar("LIB_EXT")); return i; } static char *strrpbrk(char *str, char *brk, int len) { char *ptr = str+len; while((--ptr) >= str) { char *c = brk; while(*c) { if(*(c++) == *ptr) return ptr; } } return NULL; } int main(int argc, char **argv) { FILE *f; int do_level = 0, wait_for_done = 0; int did_cmds = 0, did_else = 0; int curr_line = 0; char *ptr, *nextline = NULL, *nextcmd = NULL; int ret = 0, tmp = 0, i; int ignored_errors = 0; int verbose = 0; int shh; setenv("CC", "gcc", 0); setenv("CXX", "g++", 0); setenv("LD", "gcc", 0); setenv("OUT_OPT", "-o ", 0); setenv("SRC_OPT", "-c ", 0); setenv("DEP_OPT", "-MMD -MF ", 0); setenv("OBJ_EXT", ".o", 0); setenv("OBJ_DIR", ".", 0); setenv("DEP_EXT", ".d", 0); setenv("DEP_DIR", ".", 0); #ifdef _WIN32 setenv("EXE_EXT", ".exe", 0); #else setenv("EXE_EXT", "", 0); #endif setenv("AR", "ar", 0); setenv("AR_OPT", "", 0); setenv("LIB_PRE", "lib", 0); setenv("LIB_EXT", ".a", 0); setenv("CPPFLAGS", "", 0); setenv("CFLAGS", "", 0); setenv("CXXFLAGS", "", 0); setenv("LDFLAGS", "", 0); /* Open the default file */ f = fopen("default.cbd", "r"); if(!f) { fprintf(stderr, "\n\n\n*** Critical Error ***\n" "Could not open 'default.cbd'!\n\n"); exit(1); } main_loop_start: while(1) { int line_count, len; int ignore_err = 0; int in_quote = 0; int has_do = 0; int reverse; /* If we already have the next line set, go do it */ if(nextcmd) { memmove(linebuf, nextcmd, strlen(nextcmd)+1); nextcmd = NULL; goto reparse; } /* If we already have the next line set, go do it */ if(nextline) { memmove(linebuf, nextline, strlen(nextline)+1); nextline = NULL; goto reparse; } /* Grab the next line and increment the line count */ if(fgets(linebuf, sizeof(linebuf), f) == NULL) { if(!invoke_backup[0].f) break; /* If end of file, check if we should uninvoke and continue */ for(i = 1;i <= INVOKE_BKP_SIZE;++i) { if(i == INVOKE_BKP_SIZE || !invoke_backup[i].f) { --i; fclose(f); f = invoke_backup[i].f; invoke_backup[i].f = NULL; strcpy(linebuf, invoke_backup[i].bkp_lbuf); free(invoke_backup[i].bkp_lbuf); if(invoke_backup[i].bkp_nextline) { nextline = linebuf+strlen(linebuf)+1; strcpy(nextline, invoke_backup[i].bkp_nextline); free(invoke_backup[i].bkp_nextline); } curr_line = invoke_backup[i].bkp_line; did_else = invoke_backup[i].bkp_did_else; did_cmds = invoke_backup[i].bkp_did_cmds; do_level = invoke_backup[i].bkp_do_level; goto main_loop_start; } } break; } ++curr_line; line_count = 0; ptr = linebuf; do { while((ptr=strpbrk(ptr, "$'\"#")) != NULL) { /* Enter in-quote mode (disables ''-quoting and #-comments) */ if(*ptr == '\"') { in_quote ^= 1; ++ptr; continue; } /* A '#' kills the rest of the line */ if(*ptr == '#' && !in_quote) { char *next = strchr(ptr, '\n'); if(next) memmove(ptr, next, strlen(next)+1); else *ptr = 0; continue; } /* Jump past a hard quote (don't expand anything) */ if(*ptr == '\'' && !in_quote) { int add_count = 0; char *next = strchr(ptr+1, '\''); /* Find the closing '. If it's not found, assume it's a * multi-line quote */ while(!next) { next = ptr+strlen(ptr); if(sizeof(linebuf) == next-linebuf) { printf("!!! Error, line %d !!!\n" "Unterminated hard quote!", curr_line); ret = -1; goto end; } if(fgets(next, sizeof(linebuf)-(next-linebuf), f) == NULL) break; next = strchr(ptr+1, '\''); ++add_count; } ptr = next; curr_line += add_count; ++ptr; continue; } /* Apend the next line to this one */ if(strcmp(ptr, "$\n") == 0) { ptr += 2; if(fgets(ptr, sizeof(linebuf)-(ptr-linebuf), f) == NULL) break; ++curr_line; continue; } ++ptr; } if(!in_quote) break; ptr = linebuf+strlen(linebuf); if(fgets(ptr, sizeof(linebuf)-(ptr-linebuf), f) == NULL) { printf("!!! Error, line %d !!!\n" "Unterminated quote!", curr_line); ret = -1; goto end; } ++line_count; } while(1); curr_line += line_count; /* Check for the special '$' char, expanding variables as needed */ do { len = strlen(linebuf); in_quote = 0; tmp = 0; ptr = linebuf; while((ptr=strrpbrk(linebuf, "$'\"", len)) != NULL) { len = ptr-linebuf; /* Enter in-quote mode (disables ''-quoting and #-comments) */ if(*ptr == '\"') { in_quote ^= 1; continue; } /* A '#' kills the rest of the line */ if(*ptr == '#' && !in_quote) { char *next = strchr(ptr, '\n'); if(next) memmove(ptr, next, strlen(next)+1); else *ptr = 0; continue; } /* Jump past a hard quote (don't expand anything) */ if(*ptr == '\'' && !in_quote) { char *next; *ptr = 0; next = strrchr(linebuf, '\''); if(!next) { printf("!!! Error, line %d !!!\n" "Unterminated hard quote!", curr_line); ret = -1; goto end; } *ptr = '\''; len = next-linebuf; continue; } ++ptr; /* Insert the environment var named between the {} */ if(*ptr == '{') { char *end = strchr(ptr, '}'); if(!end) end = ptr+strlen(ptr); else *(end++) = 0; *(--ptr) = 0; snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, getvar(ptr+2), end); strcpy(linebuf, buffer); tmp = 1; continue; } /* Run a special command, replacing the section */ if(*ptr == '(') { char *next = strchr(ptr, ')'), *opt; if(!next) continue; tmp = 1; *(ptr-1) = 0; *(next++) = 0; ++ptr; opt = extract_word(&ptr); /* Replaces the section with the specified command line * option's value (in the format 'option=value') */ if(strcasecmp(ptr, "getoptval") == 0) { const char *val = ""; int len; len = snprintf(buffer, sizeof(buffer), "%s=", opt); for(i = 1;i < argc;++i) { if(strncasecmp(buffer, argv[i], len) == 0) { val = argv[i]+len; break; } } snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, val, next); strcpy(linebuf, buffer); continue; } /* Returns a library-style name from the specified * filename */ if(strcasecmp(ptr, "libname") == 0) { libify_name(obj, sizeof(obj), opt); snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, obj, next); strcpy(linebuf, buffer); continue; } if(strcasecmp("ifeq", ptr) == 0) { char *var2; char *val; var2 = strchr(opt, ','); if(!var2) { printf("\n\n!!! Error, line %d !!!\n" "Malformed 'ifeq' sub-command!\n\n", curr_line); ret = 1; goto end; } *(var2++) = 0; val = strchr(var2, ','); if(!val) { printf("\n\n!!! Error, line %d !!!\n" "Malformed 'ifeq' sub-command!\n\n", curr_line); ret = 1; goto end; } *(val++) = 0; if(strcmp(opt, var2) == 0) { char *sep = strchr(val, ','); if(sep) *sep = 0; } else { val = strchr(val, ','); if(val) ++val; } snprintf(buffer, sizeof(buffer), "%s%s%s", linebuf, (val?val:""), next); strcpy(linebuf, buffer); continue; } printf("\n\n!!! Error, line %d !!!\n" "Unknown sub-command '%s'\n\n", curr_line, ptr); goto end; } } } while(tmp); /* Now check for '$'-escapes */ ptr = linebuf; while((ptr=strpbrk(ptr, "$'\"")) != NULL) { if(*ptr == '"') { ptr = strchr(ptr+1, '"'); if(!ptr) break; continue; } if(*ptr == '\'' && !in_quote) { ptr = strchr(ptr+1, '\''); if(!ptr) break; continue; } ++ptr; /* Just a normal "escaped" character, pull the rest of the line * back one. '$\n' will be handled later */ if(*ptr != '\n') memmove(ptr-1, ptr, strlen(ptr)+1); else ++ptr; } reparse: reverse = 0; shh = 0; /* Get the next line */ if(!nextline) { int in_quotes = 0; nextline = linebuf; while(*nextline && *nextline != '\n') { if(*nextline == '"') in_quotes ^= 1; if(!in_quotes) { if(*nextline == '\'') { nextline = strchr(nextline+1, '\''); if(!nextline) break; } if(nextline[0] == '$' && nextline[1] == '\n') memmove(nextline, nextline+1, strlen(nextline)); } ++nextline; } if(nextline) { if(*nextline) *(nextline++) = 0; if(!(*nextline)) nextline = NULL; } } /* Chew up leading whitespace */ for(i = 0;linebuf[i];++i) { if(!isspace(linebuf[i])) { if(i > 0) { memmove(linebuf, linebuf+i, strlen(linebuf)+1-i); i = 0; } break; } } if(!linebuf[i]) continue; /* Find the end of the command name */ ptr = linebuf; while(*ptr && !isspace(*ptr)) ++ptr; if(*ptr) { /* If found, NULL it and get the beginning of the option */ tmp = *ptr; *(ptr++) = 0; while(isspace(*ptr) && *ptr) ++ptr; } /* Check for special 'level'ing commands */ /* The 'do' command pushes us up a level, and checks for the next * if-type command, which itself will let us know if we should start * ignoring commands */ if(strcasecmp("do", linebuf) == 0) { has_do = 1; ++do_level; memmove(linebuf, ptr, strlen(ptr)+1); goto reparse; } /* 'else' toggles ignoring commands at the current level */ if(strcasecmp("else", linebuf) == 0) { if(do_level <= 0) { fprintf(stderr, "\n\n!!! Error, line %d !!!\n" "'else' statement encountered without 'do'!\n", curr_line); goto end; } /* TODO: allow another if-type command to follow an else on the * same level */ if(!(wait_for_done & (1<<(do_level-1)))) { wait_for_done |= 1<<(do_level-1); did_cmds |= 1<<(do_level-1); has_do = 0; } if(!(did_cmds & (1<<(do_level-1)))) { wait_for_done &= ~(1<<(do_level-1)); has_do = 1; } memmove(linebuf, ptr, strlen(ptr)+1); goto reparse; } /* 'done' takes us down a level */ if(strcasecmp("done", linebuf) == 0) { if(do_level <= 0) { fprintf(stderr, "\n\n!!! Error, line %d !!!\n" "'done' statement encountered without 'do'!\n", curr_line); goto end; } wait_for_done &= ~(1<<(--do_level)); did_else &= ~(1< loaded_files && (*(curr-1) == '\'' || *(curr-1) == '"')) c = *(curr-1); i = 0; while(*cmd_ptr) { do { nuller = strchr(cmd_ptr, '<'); if(!nuller || (nuller[1] == '@' && nuller[2] == '>')) break; cmd_ptr = nuller+1; } while(1); if(!nuller) break; *nuller = 0; i += snprintf(buffer+i, sizeof(buffer)-i, "%s%s", cmd_ptr, curr); *nuller = '<'; cmd_ptr = nuller+3; } i += snprintf(buffer+i, sizeof(buffer)-i, "%s", cmd_ptr); if(!shh) { printf("%s\n", buffer); fflush(stdout); } if((ret=system(buffer)) != 0) { tmp = 1; if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } curr += strlen(curr); if(*next) { *(curr++) = c; if(curr < next) memmove(curr, next, strlen(next)+1); } } ret = tmp; continue; } /* Prints a string to the console. If a '.' char is used at the * beginning of string, it will be skipped */ if(strcasecmp("echo", linebuf) == 0) { if(ptr[0] == '.') ++ptr; printf("%s\n", ptr); fflush(stdout); continue; } /* Prints a string to the console without a newline. If a '.' char is * used at the beginning of string, it will be skipped */ if(strcasecmp("put", linebuf) == 0) { if(ptr[0] == '.') ++ptr; printf("%s", ptr); fflush(stdout); continue; } /* Creates/truncates a file and writes a string to it */ if(strcasecmp("writefile", linebuf) == 0) { char *str; FILE *o; str = extract_word(&ptr); o = fopen(ptr, "w"); if(!o) { ret = 1; if(!ignore_err) { printf("Could not create file '%s'!\n", ptr); goto end; } if(ignore_err < 2) { printf("Could not create file '%s'!\n" "--- Error %d ignored. ---\n\n", ptr, ++ignored_errors); fflush(stdout); } continue; } if(str[0] == '.') ++str; fprintf(o, "%s\n", str); fclose(o); continue; } /* Appends a string to a file */ if(strcasecmp("appendfile", linebuf) == 0) { char *str; FILE *o; str = extract_word(&ptr); o = fopen(ptr, "a"); if(!o) { ret = 1; if(!ignore_err) { printf("Could not create file '%s'!\n", ptr); goto end; } if(ignore_err < 2) { printf("Could not create file '%s'!\n" "--- Error %d ignored. ---\n\n", ptr, ++ignored_errors); fflush(stdout); } continue; } if(str[0] == '.') ++str; fprintf(o, "%s\n", str); fclose(o); continue; } /* Jumps to the specified label. A label is denoted by a '#:' combo * prepended to it at the beginning of a line */ if(strcasecmp("goto", linebuf) == 0) { int src_line; char *lbl; lbl = strdup(ptr); if(!lbl) { fprintf(stderr, "\n\n\n** Critical Error **\n" "Out of memory duplicating string '%s'\n\n", lbl); ret = -1; goto end; } rewind(f); src_line = curr_line; curr_line = 0; while(fgets(linebuf, sizeof(linebuf), f) != NULL) { ++curr_line; if(linebuf[0] == '#' && linebuf[1] == ':') { ptr = strpbrk(linebuf, "\r\n"); if(ptr) *ptr = 0; if(strcasecmp(linebuf+2, lbl) == 0) { free(lbl); nextline = NULL; goto main_loop_start; } } } fprintf(stderr, "\n\n!!! Error, line %d !!!\n" "Label target '%s' not found!\n\n", src_line, lbl); free(lbl); ret = -1; goto end; } /* Stores a list of paths to look for source files in. Passing only * '.' clears the list. */ if(strcasecmp("src_paths", linebuf) == 0) { unsigned int count = 0; char *next; while(src_paths[count] && count < SRC_PATH_SIZE) { free(src_paths[count]); src_paths[count] = NULL; ++count; } if(strcmp(ptr, ".") == 0) continue; count = 0; while(*ptr) { if(count >= SRC_PATH_SIZE) { printf("\n\n!!! Error, line %d !!!\n" "Too many source paths specified!\n\n", ++curr_line); ret = -1; goto end; } next = extract_word(&ptr); src_paths[count] = strdup(ptr); if(!src_paths[count++]) { fprintf(stderr, "\n\n\n** Critical Error **\n" "Out of memory duplicating string " "'%s'\n\n", ptr); ret = -1; goto end; } ptr = next; } continue; } /* Deletes the specified executables, appending 'EXE_EXT' to the names * as needed */ if(strcasecmp("rmexec", linebuf) == 0) { char *next; do { next = extract_word(&ptr); snprintf(buffer, sizeof(buffer), "%s%s", ptr, getvar("EXE_EXT")); if(stat(buffer, &statbuf) == -1 && errno == ENOENT) continue; if(!shh) { if(verbose) printf("remove(\"%s\");\n", buffer); else printf("Deleting %s...\n", buffer); fflush(stdout); } if((ret=remove(buffer)) != 0) { if(ignore_err < 2) printf("!!! Could not delete file !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } } while(*(ptr=next)); continue; } /* Deletes the specified libraries, prepending 'LIB_PRE' to the * filename portions and appending with 'LIB_EXT' */ if(strcasecmp("rmlib", linebuf) == 0) { char *next; do { next = extract_word(&ptr); libify_name(buffer, sizeof(buffer), ptr); if(stat(buffer, &statbuf) == -1 && errno == ENOENT) continue; if(!shh) { if(verbose) printf("remove(\"%s\");\n", buffer); else printf("Deleting %s...\n", buffer); fflush(stdout); } if((ret=remove(buffer)) != 0) { if(ignore_err < 2) printf("!!! Could not delete file !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } } while(*(ptr=next)); continue; } /* Removes a list of object files and their associated dependancy * files, replacing the extension of the named file as necesarry */ if(strcasecmp("rmobj", linebuf) == 0) { char *ext; char *next; do { next = extract_word(&ptr); ext = strrchr(ptr, '/'); if(!ext) ext = ptr; ext = strrchr(ext, '.'); if(ext) *ext = 0; snprintf(buffer, sizeof(buffer), "%s/%s%s", getvar("OBJ_DIR"), ptr, getvar("OBJ_EXT")); if(ext) *ext = '.'; if(stat(buffer, &statbuf) == 0 || errno != ENOENT) { if(!shh) { if(verbose) printf("remove(\"%s\");\n", buffer); else printf("Deleting %s...\n", buffer); fflush(stdout); } if((ret=remove(buffer)) != 0) { if(ignore_err < 2) printf("!!! Could not delete file !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); } } if(ext) *ext = 0; snprintf(buffer, sizeof(buffer), "%s/%s%s", getvar("DEP_DIR"), ptr, getvar("DEP_EXT")); if(ext) *ext = '.'; if(stat(buffer, &statbuf) == -1 && errno == ENOENT) continue; if(!shh) { if(verbose) printf("remove(\"%s\");\n", buffer); else printf("Deleting %s...\n", buffer); fflush(stdout); } if((ret=remove(buffer)) != 0) { if(ignore_err < 2) printf("!!! Could not delete file !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } } while(*(ptr=next)); continue; } /* Removes a list of files or empty directories */ if(strcasecmp("rm", linebuf) == 0) { char *next; do { next = extract_word(&ptr); if(stat(ptr, &statbuf) == -1 && errno == ENOENT) continue; if(!shh) { if(verbose) printf("remove(\"%s\");\n", ptr); else printf("Deleting %s...\n", ptr); fflush(stdout); } if((ret=remove(ptr)) != 0) { if(ignore_err < 2) printf("!!! Could not delete !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } } while(*(ptr=next)); continue; } /* Creates a directory (with mode 700 in Unix) */ if(strcasecmp("mkdir", linebuf) == 0) { extract_word(&ptr); if(!shh) { if(!verbose) printf("Creating directory %s/...\n", ptr); #ifdef _WIN32 else printf("mkdir(\"%s\");\n", ptr); fflush(stdout); } if((ret=mkdir(ptr)) != 0) #else else printf("mkdir(\"%s\", S_IRWXU);\n", ptr); fflush(stdout); } if((ret=mkdir(ptr, S_IRWXU)) != 0) #endif { if(ignore_err < 2) printf("!!! Could not create directory !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } continue; } /* Enables/disables command verboseness */ if(strcasecmp("verbose", linebuf) == 0) { verbose = (atoi(ptr) != 0); continue; } /* Leaves the current script, falling back to the previous if the * current was started with the invoke command. Otherwise, it behaves * like exit */ if(strcasecmp("uninvoke", linebuf) == 0) { ret = atoi(ptr); if(!invoke_backup[0].f) goto end; for(i = 1;i <= INVOKE_BKP_SIZE;++i) { if(i == INVOKE_BKP_SIZE || !invoke_backup[i].f) { --i; fclose(f); f = invoke_backup[i].f; invoke_backup[i].f = NULL; strcpy(linebuf, invoke_backup[i].bkp_lbuf); free(invoke_backup[i].bkp_lbuf); if(invoke_backup[i].bkp_nextline) { nextline = linebuf+strlen(linebuf)+1; strcpy(nextline, invoke_backup[i].bkp_nextline); free(invoke_backup[i].bkp_nextline); } curr_line = invoke_backup[i].bkp_line; did_else = invoke_backup[i].bkp_did_else; did_cmds = invoke_backup[i].bkp_did_cmds; do_level = invoke_backup[i].bkp_do_level; break; } } if(ret != 0) { if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } continue; } /* Copies a file */ if(strcasecmp("copy", linebuf) == 0) { char *dfile; dfile = extract_word(&ptr); if(!(*dfile)) { if(ignore_err < 2) printf("\n\n!!! Error, line %d !!! \n" "Improper arguments to 'copy'!\n", curr_line); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n", ++ignored_errors); fflush(stdout); continue; } extract_word(&dfile); if(dfile[strlen(dfile)-1] == '/') { char *fn = strrchr(ptr, '/'); snprintf(obj, sizeof(obj), "%s%s", dfile, (fn?(fn+1):ptr)); dfile = obj; } if(!shh) { if(verbose) printf("copy_file(\"%s\", \"%s\");\n", ptr, dfile); else printf("Copying '%s' to '%s'...\n", ptr, dfile); fflush(stdout); } if(copy_file(ptr, dfile) != 0) { if(ignore_err < 2) printf("!!! Could not copy !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } continue; } /* Copies a library file, prepending and appending the names as * necesarry */ if(strcasecmp("copylib", linebuf) == 0) { char *dfile; dfile = extract_word(&ptr); if(!(*dfile)) { if(ignore_err < 2) printf("\n\n!!! Error, line %d !!! \n" "Improper arguments to 'copylib'!\n", curr_line); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n", ++ignored_errors); fflush(stdout); continue; } extract_word(&dfile); if(dfile[strlen(dfile)-1] == '/') { char *fn = strrchr(ptr, '/'); snprintf(obj, sizeof(obj), "%s%s", dfile, (fn?(fn+1):ptr)); libify_name(buffer, sizeof(buffer), obj); } else libify_name(buffer, sizeof(buffer), dfile); libify_name(obj, sizeof(obj), ptr); if(!shh) { if(verbose) printf("copy_file(\"%s\", \"%s\");\n", obj, buffer); else printf("Copying '%s' to '%s'...\n", obj, buffer); fflush(stdout); } if(copy_file(obj, buffer) != 0) { if(ignore_err < 2) printf("!!! Could not copy !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } continue; } /* Copies an executable file, appending the names as necesarry */ if(strcasecmp("copyexec", linebuf) == 0) { char *dfile; dfile = extract_word(&ptr); if(!(*dfile)) { if(ignore_err < 2) printf("\n\n!!! Error, line %d !!! \n" "Improper arguments to 'copyexec'!\n", curr_line); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n", ++ignored_errors); fflush(stdout); continue; } extract_word(&dfile); if(dfile[strlen(dfile)-1] == '/') { char *fn = strrchr(ptr, '/'); snprintf(obj, sizeof(obj), "%s%s", dfile, (fn?(fn+1):ptr)); snprintf(buffer, sizeof(buffer), "%s%s", obj, getvar("EXE_EXT")); } else snprintf(buffer, sizeof(buffer), "%s%s", dfile, getvar("EXE_EXT")); libify_name(obj, sizeof(obj), ptr); snprintf(obj, sizeof(obj), "%s%s", ptr, getvar("EXE_EXT")); if(!shh) { if(verbose) printf("copy_file(\"%s\", \"%s\");\n", obj, buffer); else printf("Copying '%s' to '%s'...\n", obj, buffer); fflush(stdout); } if(copy_file(obj, buffer) != 0) { if(ignore_err < 2) printf("!!! Could not copy !!!\n"); if(!ignore_err) goto end; if(ignore_err < 2) printf("--- Error %d ignored. ---\n\n", ++ignored_errors); fflush(stdout); } continue; } /* Exits the script with the specified exitcode */ if(strcasecmp("exit", linebuf) == 0) { ret = atoi(ptr); goto end; } printf("\n\n!!! Error, line %d !!!\n" "Unknown command '%s'\n\n", curr_line, linebuf); break; } end: fflush(stdout); i = 0; while(src_paths[i] && i < SRC_PATH_SIZE) free(src_paths[i++]); i = 0; while(i < INVOKE_BKP_SIZE && invoke_backup[i].f) { fclose(invoke_backup[i].f); free(invoke_backup[i].bkp_lbuf); free(invoke_backup[i].bkp_nextline); ++i; } free(loaded_files); free(sources); fclose(f); return ret; }