LoggerFile* loggerFileInitFromPath(LoggerFile* file_, const char* path_) { assert(file_ && "file_ must be not NULL!"); if (!loggerMakePathAbs(path_, file_->path, 0)) { /* fallback to the given path */ strcpy(file_->path, path_); } return file_; }
/** * Processes an command line argument for a GCC like command. * * @param state_ the current state of the parser. * @param arg_ the current command line argument. * @param action the current action. * @return the new state. */ static GccArgsState processArgument( GccArgsState state_, const char* arg_, LoggerAction* action_) { char argToAdd[PATH_MAX]; strcpy(argToAdd, arg_); if (state_ == InOutputArg) { if (!loggerMakePathAbs(arg_, argToAdd, 0)) { strcpy(argToAdd, arg_); } loggerFileInitFromPath(&action_->output, argToAdd); state_ = Normal; } else if (strcmp(arg_, "-o") == 0) { state_ = InOutputArg; } else if (arg_[0] == '-' && (arg_[1] == 'I' || arg_[1] == 'L') && arg_[2]) { /* This is a -I or -L option with a path */ char fullPath[PATH_MAX]; if (loggerMakePathAbs(arg_ + 2, fullPath, 0)) { argToAdd[2] = 0; strcat(argToAdd, fullPath); } } else { char fullPath[PATH_MAX]; if (loggerMakePathAbs(argToAdd, fullPath, 1)) { char* ext = loggerGetFileExt(fullPath, 1); if (ext) { int i; for (i = 0; srcExts[i]; ++i) { if (strcmp(srcExts[i], ext) == 0) { strcpy(argToAdd, fullPath); loggerVectorAddUnique(&action_->sources, loggerStrDup(fullPath), (LoggerCmpFuc) &strcmp); break; } } } free(ext); } } if (argToAdd[0]) { loggerVectorAdd(&action_->arguments, loggerStrDup(argToAdd)); } return state_; }
/** * Tries to get the default header includes from a gcc(like) command and stores * the result into the given vector. * * @param prog_ the gcc like program / command. * @param args_ a vector for the arguments. */ static void getDefaultArguments(const char* prog_, LoggerVector* args_) { char command[PATH_MAX]; FILE* cmdOut; char* line = NULL; size_t lineSize = 0; ssize_t readSize; int incStarted = 0; strcpy(command, prog_); strcat(command, " -xc++ -E -v - < /dev/null 2>&1"); cmdOut = popen(command, "r"); if (!cmdOut) { return; } while ((readSize = getline(&line, &lineSize, cmdOut)) >= 0) { char fullPath[PATH_MAX] = "-I"; char* pathEnd; char* pathStart; if (!incStarted) { if (strstr(line, "#include <...> search starts here")) { incStarted = 1; } continue; } else if (strstr(line, "End of search list")) { break; } /* Drop the new line character from the end of the line and the leading whitespaces. */ for (pathStart = line; *pathStart && isspace(*pathStart); ++pathStart) {} for (pathEnd = pathStart; *pathEnd && !isspace(*pathEnd); ++pathEnd) {} *pathEnd = 0; if (pathStart[0] == 0) { /* WTF??? */ continue; } if (!loggerMakePathAbs(pathStart, fullPath + 2, 0)) { /* Invalid path, skip */ continue; } if (isGccLibPath(fullPath)) { /* We have to skip builtin gcc headers, we only need the paths to the stdlib */ continue; } loggerVectorAdd(args_, loggerStrDup(fullPath)); } free(line); pclose(cmdOut); }
/** * Processes an command line argument for a GCC like command. * * @param state_ the current state of the parser. * @param arg_ the current command line argument. * @param action the current action. * @return the new state. */ static GccArgsState processArgument( GccArgsState state_, const char* arg_, LoggerAction* action_) { char argToAdd[PATH_MAX]; strcpy(argToAdd, arg_); if (state_ == InOutputArg) { if (!loggerMakePathAbs(arg_, argToAdd, 0)) { strcpy(argToAdd, arg_); } loggerFileInitFromPath(&action_->output, argToAdd); state_ = Normal; } else if (strcmp(arg_, "-o") == 0) { state_ = InOutputArg; } else if (arg_[0] == '-' && ((arg_[1] == 'W' && (arg_[2] == 'l' || arg_[2] == 'p')) || arg_[1] == 'M')) { /* This is a -Wl linker option * -Wl,-Map,output.map * or a -Wp prepocessor option * -Wp,option * also matches for options like -Wpedantic * handled here to skip for matching source files in * these arguments */ strcpy(argToAdd, arg_); } else if (arg_[0] == '-' && arg_[1] == 'D') { /* Match for macro definition -D * handled here to skip for matching source files in * these arguments */ strcpy(argToAdd, arg_); } else if (arg_[0] == '-' && (arg_[1] == 'I' || arg_[1] == 'L') && arg_[2]) { /* This is a -I or -L option with a path */ char fullPath[PATH_MAX]; if (loggerMakePathAbs(arg_ + 2, fullPath, 0)) { argToAdd[2] = 0; strcat(argToAdd, fullPath); } } else { char fullPath[PATH_MAX]; if (loggerMakePathAbs(argToAdd, fullPath, 1)) { char* ext = loggerGetFileExt(fullPath, 1); if (ext) { int i; for (i = 0; srcExts[i]; ++i) { if (strcmp(srcExts[i], ext) == 0) { strcpy(argToAdd, fullPath); loggerVectorAddUnique(&action_->sources, loggerStrDup(fullPath), (LoggerCmpFuc) &strcmp); break; } } } free(ext); } } if (argToAdd[0]) { loggerVectorAdd(&action_->arguments, loggerStrDup(argToAdd)); } return state_; }
int loggerJavacParserCollectActions( const char* prog_, const char* toolName_, const char* const argv_[], LoggerVector* actions_) { ParserData data; size_t i; assert(prog_ == prog_); /* suppress unused variable */ data.hasSourcePath = 0; data.state = Normal; loggerVectorInit(&data.commonArgs); loggerVectorInit(&data.sources); memset(data.classdir, 0, sizeof(data.classdir)); loggerVectorAdd(&data.commonArgs, loggerStrDup(toolName_)); for (i = 1; argv_[i]; ++i) { if (argv_[i][0] == '@') { size_t j; LoggerVector fargs; loggerVectorInit(&fargs); readArgumentsFromFile(argv_[i] + 1, &fargs); for (j = 0; j < fargs.size; ++j) { processArg((const char*) fargs.data[j], &data); } loggerVectorClear(&fargs); } else { processArg(argv_[i], &data); } } if (!data.hasSourcePath) { char workdir[PATH_MAX]; if (loggerMakePathAbs(".", workdir, 0)) { loggerVectorAdd(&data.commonArgs, loggerStrDup("-sourcepath")); loggerVectorAdd(&data.commonArgs, loggerStrDup(workdir)); } } for (i = 0; i < data.sources.size; ++i) { char outputFile[PATH_MAX]; const char* src = (char*) data.sources.data[i]; LoggerAction* action = loggerActionNew(toolName_); if (!action) { continue; } loggerVectorAddFrom(&action->arguments, &data.commonArgs, NULL, (LoggerDupFuc) &loggerStrDup); loggerVectorAdd(&action->arguments, loggerStrDup(src)); loggerVectorAdd(&action->sources, loggerStrDup(src)); if (data.classdir[0] != 0) { char* fname = loggerGetFileName(src, 1); strcpy(outputFile, data.classdir); strcat(outputFile, "/"); strcat(outputFile, fname); strcat(outputFile, ".class"); free(fname); } else { char* path = loggerGetFilePathWithoutExt(src); strcpy(outputFile, path); strcat(outputFile, ".class"); free(path); } loggerFileInitFromPath(&action->output, outputFile); loggerVectorAdd(actions_, action); } loggerVectorClear(&data.commonArgs); loggerVectorClear(&data.sources); return 1; }
/** * Processes a single argument. * * @param arg_ the current argument. * @param data_ the state data of the parser function. */ static void processArg(const char* arg_, ParserData* data_) { size_t argToAddSize = PATH_MAX; char* argToAdd ; char* ext; argToAdd = (char*) malloc(sizeof(char) * argToAddSize); if (!argToAdd) { /* NO MEM! */ return; } strcpy(argToAdd, arg_); if (data_->state == InClassDir) { if (!loggerMakePathAbs(arg_, data_->classdir, 0)) { strcpy(data_->classdir, arg_); } strcpy(argToAdd, data_->classdir); data_->state = Normal; } else if (data_->state == InClassPath) { handleClassPath(&argToAdd, &argToAddSize, arg_); data_->state = Normal; } else if (strcmp(arg_, "-sourcepath") == 0) { data_->hasSourcePath = 1; } else if (strcmp(arg_, "-d") == 0) { data_->state = InClassDir; } else if (strcmp(arg_, "-cp") == 0 || strcmp(arg_, "-classpath") == 0) { data_->state = InClassPath; } else if ((ext = loggerGetFileExt(arg_, 1))) { int isSource = 0; if (strcmp(ext, "java") == 0) { char path[PATH_MAX]; if (loggerMakePathAbs(arg_, path, 0)) { loggerVectorAddUnique(&data_->sources, loggerStrDup(path), (LoggerCmpFuc) &strcmp); isSource = 1; } } if (isSource) { argToAdd[0] = 0; } free(ext); } if (argToAdd[0]) { loggerVectorAdd(&data_->commonArgs, loggerStrDup(argToAdd)); } free(argToAdd); }
/** * Handles a class path argument (resolves the globs and makes relative paths). * The result will be in the *resCp_ buffer. If there is not enough space in * the memory buffer then the buffer will be reallocated and its new size * stored in the *resCpSize_ parameter. * * @param resCp_ a pointer to a memory buffer. * @param resCpSize_ a pointer to the current size of the *resCp_ buffer. * @param cp_ the unresolved class path (-cp or -classpath parameter). * @return 0 on error, non 0 on success. */ static int handleClassPath( char** resCp_, size_t* resCpSize_, char const* cp_) { char* classPath; size_t currSize = 1; char* cpPart; **resCp_ = 0; classPath = (char*) malloc((strlen(cp_) + 1) * sizeof(char)); strcpy(classPath, cp_); for (cpPart = strtok(classPath, ":"); cpPart; cpPart = strtok(NULL, ":")) { size_t i; char** words; wordexp_t we; memset(&we, 0, sizeof(wordexp_t)); if (wordexp(cpPart, &we, WRDE_NOCMD | WRDE_UNDEF) != 0) { strcpy(*resCp_, cp_); free(classPath); return 0; } words = we.we_wordv; for (i = 0; i < we.we_wordc; i++) { char path[PATH_MAX]; if (loggerMakePathAbs(words[i], path, 1) == NULL) { /* The path is malformed or does not exists! Ignore */ continue; } /* We need space for the path + a ':' character */ currSize += strlen(path) + 1; if (currSize >= *resCpSize_) { char* newMem = realloc(*resCp_, currSize * 2); if (!newMem) { /* Out of memory */ strcpy(*resCp_, cp_); free(classPath); wordfree(&we); return 0; } *resCp_ = newMem; *resCpSize_ = currSize * 2; } strcat(*resCp_, path); strcat(*resCp_, ":"); } wordfree(&we); } /* Cut down the last ':' character */ currSize = strlen(*resCp_); if ((*resCp_)[currSize - 1] == ':') { (*resCp_)[currSize - 1] = 0; } free(classPath); return 1; }