spring cleaning 1
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "liberror.h"
|
||||
|
||||
void
|
||||
exhaust_buffer(char *b, size_t s){
|
||||
size_t i;
|
||||
for(i = 0; i < s; ++i)
|
||||
if(b[i] != 0)
|
||||
putc(b[i], stdout);
|
||||
free(b);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
print_stdin(void){
|
||||
char c;
|
||||
while((c = getc(stdin)) != EOF)
|
||||
putc(c, stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
substitute(char *phrase, char *substitution, bool exit_on_first, char *name){
|
||||
char *b = (char *)calloc(strlen(phrase)+1, sizeof(char));
|
||||
size_t i;
|
||||
if(b == NULL)
|
||||
error(name, ALLOCATION_ERROR);
|
||||
while((b[strlen(phrase)-1] = getc(stdin)) != EOF){
|
||||
for(i = 0;
|
||||
b[i] == phrase[i]
|
||||
&& b[i] != 0
|
||||
&& phrase[i] != 0;
|
||||
++i);
|
||||
if(i == strlen(phrase)){
|
||||
fputs(substitution, stdout);
|
||||
for(i = 0; i < strlen(phrase);)
|
||||
b[i++] = 0;
|
||||
if(exit_on_first){
|
||||
exhaust_buffer(b, strlen(phrase)+1);
|
||||
print_stdin();
|
||||
}
|
||||
}else
|
||||
putc(*b, stdout);
|
||||
|
||||
/* There's a more efficient way to maintain a buffer here,
|
||||
* where I keep an unordered string of chars and form an
|
||||
* ordered string when I need to check against the phrase
|
||||
* to match. However it's math-intensive, which sucks not just
|
||||
* for a self-taught lamer but in general in regards to muh
|
||||
* simplicity, and the math undercuts the performance gain
|
||||
* from avoiding touching memory. Also, come on, you're never
|
||||
* gonna have a phrase longer than 100 bytes! Who cares?! */
|
||||
for(i = 0; i < strlen(phrase); ++i)
|
||||
b[i] = b[i+1];
|
||||
}
|
||||
exhaust_buffer(b, strlen(phrase)+1);
|
||||
}
|
||||
|
||||
void
|
||||
usage(char *name){
|
||||
fprintf(stdout, "Usage: %s (-fhr) [phrase] [substitution]\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
bool exit_on_first = 0;
|
||||
char c;
|
||||
char *argv0 = argv[0];
|
||||
bool regex_mode = 0;
|
||||
|
||||
while((c = getopt(argc, argv, "fhr")) != -1){
|
||||
switch(c){
|
||||
/* -f exists because there exist uses of `sed 's/foo/bar/'`
|
||||
* without the trailing `g` for global substitution that
|
||||
* would be borked if made global. Perhaps there are other ways
|
||||
* to do so that mean that this option doesn't need to be
|
||||
* implemented, but it's kind of easy to just add so
|
||||
* whatever. */
|
||||
case 'f': exit_on_first = 1;
|
||||
case 'h': usage(argv0);
|
||||
/* By default regex is not parsed; this is because regular
|
||||
* expressions are not known to the GENERAL user. The kind of
|
||||
* user that uses this utility /does/ know regex, but the kind
|
||||
* of user this utility targets does not, so don't implement
|
||||
* potentially undesirable functionality by default.
|
||||
* If you know regex you know how to look up a manpage. */
|
||||
case 'r':
|
||||
regex_mode = 1;
|
||||
break;
|
||||
case '?': default: usage(argv0);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(argc < 2 || argc > 3)
|
||||
usage(argv0);
|
||||
|
||||
if(regex_mode == 0)
|
||||
substitute(argv[0], argv[1], exit_on_first, argv0);
|
||||
else
|
||||
{ printf("Not implemented.\n"); exit(1); }
|
||||
// substitute_regex(argv[0], argv[1], exit_on_first, argv0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user