/** * The documentation is kept in the UNIX man page EndNoteTag.1 . * @since 2007-06-13 * @author Richard J. Mathar */ #include #include #include using namespace std ; /** * @return 0 if successful, 1 if the syntax is not met. * @since 2007-06-12 * @author Richard J. Mathar */ int main(int argc, char*argv[]) { /* command line option */ int c ; /* 0 if EndNote standard input, 1 if RIS */ int ristype =0 ; /* the length of the tag for RIS type inputs */ int rislen = -1 ; while ( (c=getopt(argc,argv,"R")) != -1) { switch(c) { case 'R': ristype=1 ; break ; case '?': cerr << argv[0] << ": invalid command line option " << optarg << endl ; return 1 ; } } /* States 0 = noop, 1=replace, 2 =remove. Supposed we do not see any more * command line arguments, the default is noop for EndNote and remove for RIS. */ int state = ristype ? 2 : 0 ; if ( optind >= argc ) { cerr << argv[0] << " needs at least one command line argument for useful operation\n" ; return 1 ; } /* for EndNote inputs, demand 1 or 2-letter command line arguments */ if ( ! ristype) for(int c = optind ; c < argc; c++) { if ( strlen(argv[c]) > 2+ristype ) { cerr << argv[0] << " invalid length of argument " << argv[c] << endl ; return 1 ; } } /* loop over all lines of the standard input. */ while ( !cin.eof() ) { string buf ; getline(cin,buf) ; /* Check if this starts a new tag. This is done naively: tags are all lines at least two characters long. * EndNote tags must start with a percent sign as the first character. RIS tags are any two characters * followed by one or two blanks (one blank is actually a non-standard faulty format), a dash and at * least one more blank. */ if ( buf.size() >= 2 ) { /* try to autodetect the length of the RIS Tags */ if (ristype && rislen < 0 ) { /* search for the exact position of the RIS tag, independent on * how many blanks are between the tag and the dash. */ const int firstd = buf.find(" - ") ; if ( firstd != string::npos ) rislen = firstd ; } if ( buf[0] == '%' && !ristype || ristype && rislen >=0 && buf.compare(rislen,3," - ",3) == 0 ) { /* reset state to default. */ state= ristype ? 2 : 0 ; for(int c=optind ; c < argc ; c++) { /* query whether this is a tag that is mentioned in the command line arguments. */ if ( ristype) { /* for RIS type inputs, command line arguments must be 3-letter words */ if ( strlen(argv[c]) != rislen+1 ) { cerr << argv[0] << " invalid length of argument " << argv[c] << endl ; return 1 ; } /* search for the exact position of the RIS tag, independent on * how many blanks are between the tag and the dash. */ const int firstd = buf.find(" - ") ; if ( buf.compare(0,2,argv[c],2) == 0 ) { buf.replace(0,1,"%") ; buf.replace(1,1+firstd,&argv[c][2]) ; state = 1 ; } } else { if ( buf[1] == argv[c][0] ) { if ( strlen(argv[c]) == 1 ) state = 2 ; else { state = 1 ; buf.replace(1,1,&argv[c][1]) ; } } } } } } /* blank lines reset the state */ else if ( buf.size() == 0 ) { state= ristype ? 2 : 0 ; } /* print potentially modified line */ if ( state != 2 ) cout << buf << endl ; } return 0 ; }