1
0
Fork 0
src/Wip/substitute.c

113 lines
2.9 KiB
C

#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;
}