Commit a5128783 authored by Marcus M Darden's avatar Marcus M Darden
Browse files

Create and populate the repo (initial commit)

parents
# Xcode Redirect
## Description
Use this file to help Xcode behave more like a command line shell when it
comes to dealing with file redirection. This addresses missing functionality
for:
* Input redirection (cin >>): < inputfilename
* Output redirection (cout <<): > outputfilename
* Error redirection (cerr <<): 2> errorfilename
## How to use it
### Download
First, [download the file directly] or use `curl` or `wget`.
```bash
% wget https://gitlab.umich.edu/eecs281/xcode_redirect/raw/master/xcode_redirect.hpp
or
% curl -O https://gitlab.umich.edu/eecs281/xcode_redirect/raw/master/xcode_redirect.hpp
```
### Add it to your project
In your Project Navigator or through the File Menu, you can "Add Files..." to
your project.
Navigator:
![alt text][add-files navigator]
File Menu:
![alt text][add-files menu]
Navigate to the downloaded copy of `xcode_redirect.hpp` and add it to the
project with the following settings:
Settings:
![alt text][add-files settings]
### Add redirections as needed
In the main editor window or through the Project Menu, you can
"Edit Scheme..." to add command line parameters and file redirections.
Editor:
![alt text][edit-scheme editor]
Project Menu:
![alt text][edit-scheme menu]
For each file redirection, include an entry in "Arguments Passed On Launch."
Be sure to start with a redirection (<, >, or 2>), and then include the full
absolute path to the file, surrounded in double quotes. Check the boxes to
enable or disable various configurations of redirections.
Settings:
![alt text][edit-scheme settings]
### Edit the cpp file with your `main()` function
Include the following line inside your project's `main()` function, before you
make any reference or use of `argc` or `argv`:
```c++
#include "xcode_redirect.hpp" // Add near the top of the file with main()
...
int main(int argc, char *argv[]) {
xcode_redirect(argc, argv); // Be sure to do this!
...
cin >> my_variable; // Reads from file instead of keyboard when redirected
cout << my_result; // Prints to file instead of screen when redirected
cerr << my_msg; // Prints to file instead of screen when redirected
```
[download the file directly]: https://gitlab.umich.edu/eecs281/xcode_redirect/raw/master/xcode_redirect.hpp "xcode_redirect.hpp URL"
[add-files navigator]: images/add-files-_navigator_.png "Add files to project through Project Navigator"
[add-files menu]: images/add-files-_menu_.png "Add files to project through File Menu"
[add-files settings]: images/add-files-settings.png "Add file settings"
[edit-scheme editor]: images/edit-scheme-_editor_.png "Edit project scheme through main editor window interface"
[edit-scheme menu]: images/edit-scheme-_menu_.png "Edit project scheme through Project Menu"
[edit-scheme settings]: images/edit-scheme-settings.png "Edit Arguments Passed On Launch"
//
// xcode_redirect.hpp
//
// Created by Marcus Darden on 1/13/19.
// Copyright © 2019 Marcus Darden. All rights reserved.
//
// Usage: add the following line to main().
// xcode_redirect(argc, argv);
#ifndef xcode_redirect_hpp
#define xcode_redirect_hpp
#include <iostream>
#include <cstdio>
#include <cstring>
inline char *get_filename_and_move_count(int &optind, char *argv[], int &move_count);
inline void rotate_argv(int move_count, char *argv[], int &optind, int &argc);
// REQUIRES: argc & argv from main(), and optind from getopt.h (optional)
// MODIFIES: optind is incremented until it equals argc
// argc is decremented to discount any redirected members of argv
// EFFECTS:
// Looks for extra arguments after getopt() finishes reading options.
// It replaces simple shell functionality by using freopen() to change
// stdin (from < infilename or <infilename),
// stdout (from > outfilename or >outfilename), and/or
// stderr (from 2> errfilename or 2>errfilename).
inline void xcode_redirect(int &argc, char *argv[], int optind = 1) {
char *infile = nullptr, *outfile = nullptr, *errfile = nullptr;
int move_count = 0;
while (optind < argc) {
switch (*argv[optind]) {
case '<': // redirect input formatted as '< file' or '<file'
infile = get_filename_and_move_count(optind, argv, move_count);
if (!freopen(infile, "r", stdin)) {
std::cerr << "Unable to open input file: " << infile << std::endl;
exit(1);
} // if
break;
case '>': // redirect output formatted as '> file' or '>file'
outfile = get_filename_and_move_count(optind, argv, move_count);
if (!freopen(outfile, "w", stdout)) {
std::cerr << "Unable to open output file: " << outfile << std::endl;
exit(1);
} // if
break;
case '2': // redirect error formatted as '2> file' or '2>file'
if (*(argv[optind] + 1) == '>') {
errfile = get_filename_and_move_count(optind, argv, move_count);
if (!freopen(errfile, "w", stderr)) {
std::cerr << "Unable to open error file: " << errfile << std::endl;
exit(1);
} // if
} // if
break;
default: // not a redirection parameter
move_count = 0;
} // switch
++optind;
if (move_count > 0) {
rotate_argv(move_count, argv, optind, argc);
}
} // while
} // xcode_redirect()
inline void rotate_argv(int move_count, char *argv[], int &optind, int &argc) {
int moveind = optind - move_count;
char *temp_pre1 = argv[moveind];
char *temp_pre2 = argv[moveind + 1];
while (moveind + move_count < argc) {
argv[moveind] = argv[moveind + move_count];
++moveind;
} // while
argv[moveind++] = temp_pre1;
if (move_count == 2) {
argv[moveind] = temp_pre2;
} // if
optind -= move_count;
argc -= move_count;
} // rotate_argv()
inline char *get_filename_and_move_count(int &optind, char *argv[], int &move_count) {
if (strlen(argv[optind]) > 2) {
move_count = 1;
// Must offset by 1 character (the <), offset by more if they put space(s) before filename
int offset = 1;
// Must also offset more for 2> (redirecting error output)
if (argv[optind][0] == '2')
++offset;
while (argv[optind][offset] == ' ')
++offset;
return argv[optind] + offset;
} // if
move_count = 2;
return argv[++optind];
} // get_filename_and_move_count()
#endif /* xcode_redirect_hpp */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment