/*
Generate Organic Quadruplet Nucleotide DNA Sequences From Base-N
Oligodeoxyribonucleotide Primers for Polymerase Chain Reaction
Written by Derek Callaway ( decal [AT] sdf [D0T] org )
Compile: gcc -Wall -ansi -pedantic -o oligdna oligdna.c
*/
#include<stdio.h>
#include<stdlib.h>
void usage(const char *av0) {
if(!av0)
av0 = "specdna";
fprintf(stderr, "usage: %s <file>\n", av0);
exit(EXIT_FAILURE);
}
void vexit(const char *f) {
if(!f)
f = "vexit";
perror(f);
exit(EXIT_SUCCESS);
}
static char *_B="Tcg", *_D="ATg", *_H="ATc", *_K="Tg", *_M="Ac";
static char *_N="AcTg", *_R="Ag", *_S="cg", *_V="Acg", *_W="AT", *_Y="cT";
int main(int argc, char *argv[]) {
char buf[BUFSIZ] = { 0 }, **mixs = NULL, **vals = NULL;
register FILE *fp = NULL;
register unsigned int acc = 0, cnt = 0;
if(argc < 2)
usage(*argv);
fp = fopen(argv[1], "r");
if(!fp)
vexit("fopen");
while(fgets(buf, sizeof buf, fp)) {
register char *p = NULL, **pp = NULL, **pp2 = NULL;
mixs = vals = NULL;
for(p = buf, cnt = 0, acc = 0;*p;p++)
switch(*p) {
case 'B':
case 'D':
case 'H':
case 'K':
case 'M':
case 'N':
case 'R':
case 'S':
case 'V':
case 'W':
case 'Y':
cnt++;
}
if(cnt >= acc) {
register size_t alen = 1 + cnt;
mixs = malloc(alen * sizeof *mixs);
if(!mixs)
vexit("malloc");
vals = malloc(alen * sizeof *vals);
if(!vals)
vexit("malloc");
}
for(pp = mixs, pp2 = vals, p = buf;*p;p++)
switch(*p) {
case 'B':
*pp++ = _B;
*pp2++ = _B;
break;
case 'D':
*pp++ = _D;
*pp2++ = _D;
break;
case 'H':
*pp++ = _H;
*pp2++ = _H;
break;
case 'K':
*pp++ = _K;
*pp2++ = _K;
break;
case 'M':
*pp++ = _M;
*pp2++ = _M;
break;
case 'N':
*pp++ = _N;
*pp2++ = _N;
break;
case 'R':
*pp++ = _R;
*pp2++ = _R;
break;
case 'S':
*pp++ = _S;
*pp2++ = _S;
break;
case 'V':
*pp++ = _V;
*pp2++ = _V;
break;
case 'W':
*pp++ = _W;
*pp2++ = _W;
break;
case 'Y':
*pp++ = _Y;
*pp2++ = _Y;
break;
default:
*pp++ = p;
*pp2++ = p;
}
*pp = NULL;
if(cnt)
acc = --cnt;
for(;*vals[acc];++*vals) {
register unsigned int j = 0;
if(!**vals) {
do {
vals[j] = mixs[j];
++vals[++j];
} while(j < acc && !*vals[j]);
if(j == acc && !*vals[acc])
break;
}
for(j = 0, p = buf;*p;p++)
switch(*p) {
case 'B':
case 'D':
case 'H':
case 'K':
case 'M':
case 'N':
case 'R':
case 'S':
case 'V':
case 'W':
case 'Y':
putchar(*vals[j++]);
break;
default:
putchar(*p);
}
}
}
exit(EXIT_SUCCESS);
}