Wow, documentation!

This commit is contained in:
Kat R. 2022-10-06 02:12:56 -05:00
parent 0fa85040b3
commit 354a52e1fd
5 changed files with 112 additions and 10 deletions

34
asa.c
View file

@ -9,25 +9,42 @@ int main(int argc, char ** argv) {
char c, c_temp;
for(i = 1; i < argc; i++) {
if(argv[i][0] == '-' && argv[i][1] == '\0')
/* If - is passed as an argument, set the input file to stdin */
if(argv[i][0] == '-' && argv[i][1] == '\0') {
in_file = stdin;
}
else {
/* Open the file given */
in_file = fopen(argv[i], "r");
if(in_file == NULL) {
/* If it can't open, set that we encountered an error */
/*
TODO: this should probably check errno instead of
assuming that we can't find the file
*/
fprintf(stderr, "Cannot find file %s\n", argv[i]);
error = 1;
continue;
}
}
/*
Loop through the file line by line, applying transformations based on
the first character of the line, as given by the POSIX spec.
*/
eof_reached = 0;
while(!eof_reached) {
c = fgetc(in_file);
/*
Get the first character of the line and print the right thing
*/
switch(c) {
case '1': printf("\f"); break;
case '0': printf("\n"); break;
case '+': printf("\r"); break;
case EOF: eof_reached = 1; continue;
case '1': printf("\f"); break; /* Form feed on 1 */
case '0': printf("\n"); break; /* New line on 0 */
case '+': printf("\r"); break; /* Carriage return on + */
case EOF: eof_reached = 1; continue; /* Leave on EOF */
/* Anything else, don't do anything */
}
/* Print out the rest of the line unless we hit an EOF, where we quit. */
for(c_temp = fgetc(in_file); c_temp != '\n'; c_temp = fgetc(in_file)) {
if(c_temp == EOF) {
eof_reached = 1;
@ -40,8 +57,11 @@ int main(int argc, char ** argv) {
printf("\n");
}
if(error)
/* If we ever hit an error, return 1. */
if(error) {
return 1;
else
}
else {
return 0;
}
}

View file

@ -10,6 +10,15 @@ int main(int argc, char ** argv) {
int basename_length = 0, last_slash = 0;
int suffix_length = 0;
/*
Basename takes two arguments, one for the path itself and an optional
one for a suffix to remove (e.g. ".c" to remove the C file extension).
Here, we check for that second argument to determine if we need to
remove an extension.
If there aren't multiple arguments, check if a path was even given. If
not, the POSIX spec says to just return a newline.
*/
if(argc > 2) {
suffix_present = 1;
}
@ -18,6 +27,9 @@ int main(int argc, char ** argv) {
return 0;
}
/*
If the path is just //, the POSIX spec also says to return newline
*/
if(strcmp(argv[1], "//") == 0) {
printf("\n");
return 0;
@ -25,16 +37,25 @@ int main(int argc, char ** argv) {
i = 0;
/*
Find the end of the path (probably could've just used strlen)
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
i++;
}
/*
If the last character of the path is /, then remove it
*/
if(argv[1][i-1] == '/') {
argv[1][i-1] = '\0';
}
i = 0;
/*
Find the last slash in the path
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
if(c == '/') {
last_slash = i;
@ -44,10 +65,16 @@ int main(int argc, char ** argv) {
i = last_slash + 1;
/*
Figure out how long the basename is
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
basename_length++; i++;
}
/*
Allocate memory for the basename; fail out if we can't
*/
basename = calloc(basename_length + 1, sizeof(*basename));
if(basename == NULL) {
fprintf(stderr, "%s: Could not allocate sufficient memory\n", argv[0]);
@ -56,13 +83,21 @@ int main(int argc, char ** argv) {
i = last_slash + 1;
/*
Transfer the basename to the array
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
basename[i - (last_slash + 1)] = c;
i++;
}
basename[basename_length] = '\0';
basename[basename_length] = '\0'; /* don't forget the null! */
/*
If we need to remove a suffix, check if the end of the string is
actually equal to the suffix and, if it is, replace the first character
of the suffix with a null character.
*/
if(suffix_present && strcmp(basename, argv[2]) != 0) {
i = 0;
for(c = argv[2][i]; c != '\0'; c = argv[2][i]) {
@ -84,6 +119,9 @@ int main(int argc, char ** argv) {
}
}
/*
Print the basename, free the memory, and quit!
*/
printf("%s\n", basename);
free(basename);

15
cat.c
View file

@ -12,17 +12,28 @@ int main(int argc, char *argv[]) {
int error_occurred;
/*
Check for -u and use unbuffered output if present
*/
while((c = getopt(argc, argv, "u")) != -1) {
if(c == 'u') {
using_unbuffered_output = 1;
}
}
/*
Set unbuffered output. We do this for both stdin and stdout, let setvbuf
allocate the buffer (that we don't need), _IONBF tells it to not buffer,
and we just say 15 character buffer because, well, eh, who cares?
*/
if(using_unbuffered_output) {
setvbuf(stdin, NULL, _IONBF, 15);
setvbuf(stdout, NULL, _IONBF, 15);
}
/*
If no input files were given, just open up stdin
*/
if(argc == 1 || optind == argc) {
cur_in_file = stdin;
for(c = fgetc(cur_in_file); c != EOF; c = fgetc(cur_in_file)) {
@ -31,6 +42,10 @@ int main(int argc, char *argv[]) {
fclose(cur_in_file);
}
/*
Open up each file given (or stdin if - was given), print it to stdout,
then close it and move to the next while there are still files
*/
for(i = optind; i < argc; i++) {
if(argv[i][0] == '-' && argv[i][1] == '\0') {
cur_in_file = stdin;

24
cksum.c
View file

@ -6,6 +6,10 @@
unsigned int crc32(FILE * in_file);
int count_octets(FILE * in_file);
/*
I think this can technically be computed (don't quote me on that), but it's
easier and faster to implement it as a lookup table.
*/
unsigned int crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
@ -77,14 +81,20 @@ int main(int argc, char ** argv) {
int i, error = 0;
FILE *in_file;
/*
Open each file (set that we encountered an error if we couldn't) then
print the CRC32 checksum and number of octets in the file.
*/
for(i = 1; i < argc; i++) {
in_file = fopen(argv[i], "r");
if(in_file == NULL) {
error = 1;
fprintf(stderr, "Cannot find file %s\n", argv[i]);
}
else
else {
printf("%u %d %s\n", crc32(in_file), count_octets(in_file), argv[i]);
fclose(in_file);
}
}
if(error)
@ -95,27 +105,37 @@ int main(int argc, char ** argv) {
/* Based off the CRC-32 psuedocode implementation on the Wikipedia article for CRC */
unsigned int crc32(FILE * in_file) {
/* the CRC starts off as 0xFFFFFFFF */
unsigned int crc = 0xffffffff;
int nLookupIndex;
char c;
/* Make sure we're at the start of the file */
fseek(in_file, 0, SEEK_SET);
/*
For each character, set nLookupIndex to CRC XOR that character ANDed with
256, then set the CRC to a new value by right-shifting it 8 and XORing with
the appropriate value from the lookup table
*/
for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) {
nLookupIndex = (crc ^ c) & 0xff;
crc = (crc >> 8) ^ crc32_table[nLookupIndex];
}
/* When all's said and done, invert all the bits and return. */
crc ^= 0xffffffff;
return crc;
}
int count_octets(FILE * in_file) {
int total_octets = 0;
char c;
char c; /* I may be assuming 8-bit character...uh... */
/* Ensure we're at the start */
fseek(in_file, 0, SEEK_SET);
/* Count the octets, one by one. There may be an easier way, but eh. */
for(c = fgetc(in_file); c != EOF; c = fgetc(in_file))
total_octets++;

View file

@ -6,41 +6,50 @@
int main(int argc, char ** argv) {
int i, last_slash = -1, length;
/* If no path given, print / per the POSIX spec */
if(argc == 1) {
printf("/\n");
return 0;
}
/* Same if // is given */
if(strcmp(argv[1], "//") == 0) {
printf("/\n");
return 0;
}
/* Oh, look, we use strlen here. */
length = strlen(argv[1]);
/* Replace terminal slash (if present) with null */
if(argv[1][length - 1] == '/') {
argv[1][length - 1] = '\0';
}
/* Find last slash */
for(i = 0; i < length; i++) {
if(argv[1][i] == '/') {
last_slash = i;
}
}
/* If we didn't find a slash, assume PWD per POSIX spec */
if(last_slash == -1) {
printf(".\n");
return 0;
}
/* Replace last slash with null to truncate basename */
argv[1][last_slash] = '\0';
/* If the dirname is //, /, or blank, print a single slash. */
if(strcmp(argv[1], "//") == 0 || strcmp(argv[1], "") == 0 ||
strcmp(argv[1], "/") == 0) {
printf("/\n");
return 0;
}
/* Remove any trailing slashes from the dirname */
for(i = last_slash - 1; argv[1][i] == '/'; i--) {
argv[1][i] = '\0';
}