1 /*
2 * commands.c
3 *
4 * Various functions dealing with parsing and application of commands
5 *
6 * (c) 2016 Ronny Lorenz
7 *
8 * ViennaRNA package
9 */
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19 #include <ctype.h>
20
21 #include "ViennaRNA/fold_vars.h"
22 #include "ViennaRNA/utils/basic.h"
23 #include "ViennaRNA/constraints/hard.h"
24 #include "ViennaRNA/constraints/soft.h"
25 #include "ViennaRNA/io/utils.h"
26 #include "ViennaRNA/commands.h"
27
28 /**
29 * @brief Types of commands within a list of #vrna_command_s structures
30 */
31 typedef enum {
32 VRNA_CMD_ERROR = -1,
33 VRNA_CMD_LAST = 0,
34 VRNA_CMD_HC,
35 VRNA_CMD_SC,
36 VRNA_CMD_MOTIF,
37 VRNA_CMD_UD,
38 VRNA_CMD_SD
39 } vrna_command_e;
40
41
42 /**
43 * @brief List element for commands ready for application to a #vrna_fold_compound_t
44 * @see vrna_file_commands_read(), vrna_commands_apply(), vrna_commands_free()
45 */
46 struct vrna_command_s {
47 vrna_command_e type;
48 void *data;
49 };
50
51 typedef void *(command_parser_function)(const char *line);
52
53 /*
54 #################################
55 # PRIVATE FUNCTION DECLARATIONS #
56 #################################
57 */
58 PRIVATE struct vrna_command_s parse_command(const char *line,
59 int line_number,
60 const char *filename,
61 unsigned int options);
62
63
64 PRIVATE void *parse_ud_command(const char *line);
65
66
67 PRIVATE void *parse_constraint_force(const char *line);
68
69
70 PRIVATE void *parse_constraint_prohibit(const char *line);
71
72
73 PRIVATE void *parse_constraint_con(const char *line);
74
75
76 PRIVATE void *parse_constraint_allow(const char *line);
77
78
79 PRIVATE void *parse_constraint_energy(const char *line);
80
81
82 PRIVATE void *parse_constraint(const char *line,
83 char command);
84
85
86 PRIVATE int parse_constraints_line(const char *line,
87 char command,
88 int *i,
89 int *j,
90 int *k,
91 int *l,
92 unsigned char *loop,
93 char *orientation,
94 float *e);
95
96
97 PRIVATE int apply_hard_constraint(vrna_fold_compound_t *vc,
98 void *constraint);
99
100
101 PRIVATE int apply_soft_constraint(vrna_fold_compound_t *vc,
102 void *constraint);
103
104
105 PRIVATE int apply_ud(vrna_fold_compound_t *vc,
106 void *data);
107
108
109 /*
110 #################################
111 # PRIVATE VARIABLES #
112 #################################
113 */
114
115 typedef struct {
116 char cmd[3];
117 vrna_command_e type;
118 command_parser_function *parser;
119 } parsable;
120
121
122 /* number of commands we currently know and are able to interpret */
123 #define NUM_COMMANDS 7
124
125 /* set of known parsable commands */
126 parsable known_commands[NUM_COMMANDS] = {
127 /* cmd , type , parser */
128 { "UD", VRNA_CMD_UD, parse_ud_command }, /* unstructured domain */
129 { "SD", VRNA_CMD_SD, NULL }, /* structured domain */
130 { "P", VRNA_CMD_HC, parse_constraint_prohibit }, /* prohibit base pairing */
131 { "F", VRNA_CMD_HC, parse_constraint_force }, /* force base pairing */
132 { "C", VRNA_CMD_HC, parse_constraint_con }, /* remove conflicting pairs/force nucleotide in loop context */
133 { "A", VRNA_CMD_HC, parse_constraint_allow }, /* allow (non-canonical) pairs */
134 { "E", VRNA_CMD_SC, parse_constraint_energy } /* soft constraint */
135 };
136
137 typedef struct {
138 int i;
139 int j;
140 int k;
141 int l;
142 int size;
143 unsigned char loop;
144 char orientation;
145 float e;
146 char command;
147 } constraint_struct;
148
149
150 typedef struct {
151 char *motif_name;
152 char *motif;
153 float motif_en;
154 unsigned int loop_type;
155 } ud_struct;
156
157 /*
158 #################################
159 # BEGIN OF FUNCTION DEFINITIONS #
160 #################################
161 */
162 PUBLIC int
vrna_file_commands_apply(vrna_fold_compound_t * vc,const char * filename,unsigned int options)163 vrna_file_commands_apply(vrna_fold_compound_t *vc,
164 const char *filename,
165 unsigned int options)
166 {
167 /** [Applying commands from file] */
168 int r;
169 struct vrna_command_s *cmds;
170
171 cmds = vrna_file_commands_read(filename, options);
172 r = vrna_commands_apply(vc, cmds, options);
173
174 vrna_commands_free(cmds);
175
176 return r;
177 /** [Applying commands from file] */
178 }
179
180
181 PUBLIC struct vrna_command_s *
vrna_file_commands_read(const char * filename,unsigned int options)182 vrna_file_commands_read(const char *filename,
183 unsigned int options)
184 {
185 FILE *fp;
186 char *line;
187 int num_commands, max_commands, line_number, valid;
188 struct vrna_command_s cmd, *output;
189
190 line_number = 0;
191 num_commands = 0;
192 max_commands = 15;
193 line = NULL;
194
195 if (!(fp = fopen(filename, "r"))) {
196 vrna_message_warning("Command File could not be opened!");
197 return NULL;
198 }
199
200 output = (struct vrna_command_s *)vrna_alloc(sizeof(struct vrna_command_s) * max_commands);
201
202 /* let's go through the file line by line and parse the commands */
203 while ((line = vrna_read_line(fp))) {
204 line_number++;
205 switch (*line) {
206 /* skip comment lines */
207 case '#': /* fall through */
208 case '%': /* fall through */
209 case ';': /* fall through */
210 case '/': /* fall through */
211 case '*': /* fall through */
212 case ' ': /* fall through */
213 case '\0':
214 free(line);
215 continue;
216 default:
217 cmd = parse_command((const char *)line, line_number, filename, options);
218 break;
219 }
220
221 if (cmd.type == VRNA_CMD_LAST) {
222 /* end of command list */
223 free(line);
224 break;
225 } else {
226 /* check whether command is valid in user-defined context */
227 valid = 0;
228 switch (cmd.type) {
229 case VRNA_CMD_HC:
230 valid = options & VRNA_CMD_PARSE_HC;
231 break;
232
233 case VRNA_CMD_SC:
234 valid = options & VRNA_CMD_PARSE_SC;
235 break;
236
237 case VRNA_CMD_UD:
238 valid = options & VRNA_CMD_PARSE_UD;
239 break;
240
241 case VRNA_CMD_SD:
242 valid = options & VRNA_CMD_PARSE_SD;
243 break;
244
245 default:
246 break;
247 }
248
249 if (valid) {
250 /* add command to list */
251 output[num_commands++] = cmd;
252
253 /* increase length of command list if necessary */
254 if (num_commands == max_commands) {
255 max_commands *= 1.2;
256 output = (struct vrna_command_s *)vrna_realloc(output,
257 sizeof(struct vrna_command_s) *
258 max_commands);
259 }
260 } else if ((!(options & VRNA_CMD_PARSE_SILENT)) && (!(cmd.type == VRNA_CMD_ERROR))) {
261 /* errors have been reported earlier */
262 vrna_message_warning("Ignoring forbidden command in file \"%s\":\nline %d: %s",
263 filename,
264 line_number,
265 (const char *)line);
266 }
267 }
268
269 free(line);
270 }
271
272 /* mark end of command list */
273 output = (struct vrna_command_s *)vrna_realloc(output,
274 sizeof(struct vrna_command_s) *
275 (num_commands + 1));
276 output[num_commands].type = VRNA_CMD_LAST;
277 output[num_commands].data = NULL;
278
279 /* cleanup */
280 free(line);
281
282 return output;
283 }
284
285
286 PUBLIC int
vrna_commands_apply(vrna_fold_compound_t * vc,struct vrna_command_s * commands,unsigned int options)287 vrna_commands_apply(vrna_fold_compound_t *vc,
288 struct vrna_command_s *commands,
289 unsigned int options)
290 {
291 int r = 0;
292 struct vrna_command_s *ptr;
293
294 if (vc && commands) {
295 for (ptr = commands; ptr->type != VRNA_CMD_LAST; ptr++) {
296 switch (ptr->type) {
297 case VRNA_CMD_HC:
298 if (options & VRNA_CMD_PARSE_HC)
299 r += apply_hard_constraint(vc, ptr->data);
300
301 break;
302
303 case VRNA_CMD_SC:
304 if (options & VRNA_CMD_PARSE_SC)
305 r += apply_soft_constraint(vc, ptr->data);
306
307 break;
308
309 case VRNA_CMD_UD:
310 if (options & VRNA_CMD_PARSE_UD)
311 r += apply_ud(vc, ptr->data);
312
313 break;
314
315 default: /* do nothing */
316 break;
317 }
318 }
319 }
320
321 return r;
322 }
323
324
325 PUBLIC void
vrna_commands_free(struct vrna_command_s * commands)326 vrna_commands_free(struct vrna_command_s *commands)
327 {
328 struct vrna_command_s *ptr;
329
330 if (commands) {
331 for (ptr = commands; ptr->type != VRNA_CMD_LAST; ptr++) {
332 switch (ptr->type) {
333 case VRNA_CMD_UD:
334 {
335 ud_struct *d = (ud_struct *)ptr->data;
336 free(d->motif_name);
337 free(d->motif);
338 free(ptr->data);
339 }
340 break;
341
342 default:
343 free(ptr->data);
344 break;
345 }
346 }
347 free(commands);
348 }
349 }
350
351
352 PRIVATE int
apply_ud(vrna_fold_compound_t * vc,void * data)353 apply_ud(vrna_fold_compound_t *vc,
354 void *data)
355 {
356 ud_struct *d = (ud_struct *)data;
357
358 vrna_ud_add_motif(vc, d->motif, d->motif_en, d->motif_name, d->loop_type);
359
360 return 1;
361 }
362
363
364 PRIVATE int
apply_hard_constraint(vrna_fold_compound_t * vc,void * data)365 apply_hard_constraint(vrna_fold_compound_t *vc,
366 void *data)
367 {
368 int i, j, k, l, h, cnt1, cnt2, cnt3;
369 int num_hc_up, max_hc_up;
370 vrna_hc_up_t *hc_up;
371 unsigned char t;
372 char orientation;
373 constraint_struct *constraint = (constraint_struct *)data;
374
375 i = constraint->i;
376 j = constraint->j;
377 k = constraint->k;
378 l = constraint->l;
379 t = constraint->loop;
380 orientation = constraint->orientation;
381 h = constraint->size;
382
383 /* actually apply constraints */
384 if (h == 0) {
385 /* range mode (prohibit pairs only) */
386 for (cnt1 = i; cnt1 <= j; cnt1++)
387 for (cnt2 = MAX2(cnt1 + 1, k); cnt2 <= l; cnt2++)
388 vrna_hc_add_bp(vc, cnt1, cnt2, t);
389 } else {
390 /* we'll collect hard constraints for unpairedness */
391 num_hc_up = 0;
392 max_hc_up = 15;
393 hc_up = vrna_alloc(sizeof(vrna_hc_up_t) * max_hc_up);
394
395 for (cnt1 = i; cnt1 <= j; cnt1++)
396 for (cnt2 = k; cnt2 <= l; cnt2++)
397 for (cnt3 = h; cnt3 != 0; cnt3--) {
398 if (cnt2 == 0) {
399 /* enforce unpairedness of nucleotide */
400 /* just store this constraint, we'll apply it later */
401 hc_up[num_hc_up].position = cnt1 + (cnt3 - 1);
402 hc_up[num_hc_up].options = t;
403 num_hc_up++;
404 if (num_hc_up == max_hc_up) {
405 /* increase size of hc_up if necessary */
406 max_hc_up = 1.2 * max_hc_up;
407 hc_up = (vrna_hc_up_t *)vrna_realloc(hc_up, sizeof(vrna_hc_up_t) * max_hc_up);
408 }
409 } else if ((i == j) && (j == k) && (k == l)) {
410 /* enforce pairedness of nucleotide */
411 int d = 0;
412 if (orientation != '\0')
413 d = (orientation == 'U') ? -1 : 1;
414
415 vrna_hc_add_bp_nonspecific(vc, cnt1 + (cnt3 - 1), d, t);
416 } else {
417 /* enforce / prohibit base pair */
418 vrna_hc_add_bp(vc, cnt1 + (cnt3 - 1), cnt2 - (cnt3 - 1), t);
419 }
420 }
421
422 /* add hard constraints for unpairedness */
423 if (num_hc_up > 0) {
424 hc_up[num_hc_up].position = 0; /* mark end of list */
425 vrna_hc_add_up_batch(vc, hc_up);
426 }
427
428 free(hc_up);
429 }
430
431 return 1;
432 }
433
434
435 PRIVATE int
apply_soft_constraint(vrna_fold_compound_t * vc,void * data)436 apply_soft_constraint(vrna_fold_compound_t *vc,
437 void *data)
438 {
439 int i, j, k, l, h, cnt1, cnt2, cnt3;
440 float e;
441 constraint_struct *constraint = (constraint_struct *)data;
442
443 i = constraint->i;
444 j = constraint->j;
445 k = constraint->k;
446 l = constraint->l;
447 h = constraint->size;
448 e = constraint->e;
449
450 for (cnt1 = i; cnt1 <= j; cnt1++)
451 for (cnt2 = k; cnt2 <= l; cnt2++)
452 for (cnt3 = h; cnt3 != 0; cnt3--) {
453 if ((cnt2 == 0) || ((i == j) && (j == k) && (k == l))) /* enforce nucleotide constraint */
454 vrna_sc_add_up(vc, cnt1 + (cnt3 - 1), e, VRNA_OPTION_DEFAULT);
455 else /* enforce base pair constraint */
456 vrna_sc_add_bp(vc, cnt1 + (cnt3 - 1), cnt2 - (cnt3 - 1), e, VRNA_OPTION_DEFAULT);
457 }
458
459 return 1;
460 }
461
462
463 PRIVATE struct vrna_command_s
parse_command(const char * line,int line_number,const char * filename,unsigned int options)464 parse_command(const char *line,
465 int line_number,
466 const char *filename,
467 unsigned int options)
468 {
469 struct vrna_command_s cmd;
470 int i, r;
471 char command[3];
472
473 command[0] = '\0';
474 i = NUM_COMMANDS;
475
476 r = sscanf(line, "%2c", command);
477 if (r == 1) {
478 command[2] = '\0'; /* just a precaution */
479 for (i = 0; i < NUM_COMMANDS; i++)
480 if (!strncmp(known_commands[i].cmd, command, strlen(known_commands[i].cmd)))
481 break;
482 }
483
484 if (i < NUM_COMMANDS) {
485 /* command is known, so lets try to process it */
486 cmd.data = (known_commands[i].parser) ? known_commands[i].parser(line) : NULL;
487 if (cmd.data) {
488 cmd.type = known_commands[i].type;
489 } else {
490 if (!(options & VRNA_CMD_PARSE_SILENT)) {
491 vrna_message_warning("Ignoring invalid command in file \"%s\":\nline %d: %s",
492 filename,
493 line_number,
494 line);
495 }
496
497 cmd.type = VRNA_CMD_ERROR;
498 }
499 } else {
500 if (!(options & VRNA_CMD_PARSE_SILENT)) {
501 vrna_message_warning("Ignoring unknown command in file \"%s\":\nline %d: %s",
502 filename,
503 line_number,
504 line);
505 }
506
507 cmd.type = VRNA_CMD_ERROR;
508 cmd.data = NULL;
509 }
510
511 return cmd;
512 }
513
514
515 PRIVATE void *
parse_ud_command(const char * line)516 parse_ud_command(const char *line)
517 {
518 int ret, entries_seen, max_entries, pos, pp;
519 char *ptr, *buffer;
520 float e;
521 unsigned int loop_type;
522 ud_struct *data;
523
524 buffer = (char *)vrna_alloc(sizeof(char) * (strlen(line) + 1));
525 data = (ud_struct *)vrna_alloc(sizeof(ud_struct));
526 data->motif_name = NULL;
527 data->motif = NULL;
528 ret = 0; /* error indicator */
529 entries_seen = 0; /* entries seen so far */
530 max_entries = 3; /* expected number of entries */
531 pos = 2; /* position relative to start of line */
532 pp = 0;
533
534 while (!ret && (entries_seen < max_entries) && (sscanf(line + pos, "%s%n", buffer, &pp) == 1)) {
535 pos += pp;
536 switch (entries_seen) {
537 case 0: /* motif in IUPAC format */
538 data->motif = strdup(buffer);
539 break;
540
541 case 1: /* motif energy in kcal/mol */
542 if (sscanf(buffer, "%g", &e) == 1)
543 data->motif_en = e;
544 else
545 ret = 1;
546
547 break;
548
549 case 2: /* motif loop type */
550 loop_type = 0;
551 for (ptr = buffer; *ptr != '\0'; ptr++) {
552 switch (*ptr) {
553 case 'A':
554 loop_type |= VRNA_UNSTRUCTURED_DOMAIN_ALL_LOOPS;
555 break;
556 case 'E':
557 loop_type |= VRNA_UNSTRUCTURED_DOMAIN_EXT_LOOP;
558 break;
559 case 'H':
560 loop_type |= VRNA_UNSTRUCTURED_DOMAIN_HP_LOOP;
561 break;
562 case 'I':
563 loop_type |= VRNA_UNSTRUCTURED_DOMAIN_INT_LOOP;
564 break;
565 case 'M':
566 loop_type |= VRNA_UNSTRUCTURED_DOMAIN_MB_LOOP;
567 break;
568 default:
569 ret = 1;
570 break;
571 }
572 if (ret)
573 break;
574 }
575 data->loop_type = loop_type;
576 break;
577 }
578 entries_seen++;
579 }
580
581 free(buffer);
582
583 if (ret) {
584 free(data->motif_name);
585 free(data->motif);
586 free(data);
587 return NULL;
588 }
589
590 if (data->loop_type == 0)
591 data->loop_type = VRNA_UNSTRUCTURED_DOMAIN_ALL_LOOPS;
592
593 return (void *)data;
594 }
595
596
597 PRIVATE void *
parse_constraint_force(const char * line)598 parse_constraint_force(const char *line)
599 {
600 return parse_constraint(line, 'F');
601 }
602
603
604 PRIVATE void *
parse_constraint_prohibit(const char * line)605 parse_constraint_prohibit(const char *line)
606 {
607 return parse_constraint(line, 'P');
608 }
609
610
611 PRIVATE void *
parse_constraint_con(const char * line)612 parse_constraint_con(const char *line)
613 {
614 return parse_constraint(line, 'C');
615 }
616
617
618 PRIVATE void *
parse_constraint_allow(const char * line)619 parse_constraint_allow(const char *line)
620 {
621 return parse_constraint(line, 'A');
622 }
623
624
625 PRIVATE void *
parse_constraint_energy(const char * line)626 parse_constraint_energy(const char *line)
627 {
628 return parse_constraint(line, 'E');
629 }
630
631
632 PRIVATE void *
parse_constraint(const char * line,char command)633 parse_constraint(const char *line,
634 char command)
635 {
636 int ret, i, j, k, l, h, valid;
637 unsigned char loop;
638 char orientation;
639 float e;
640 constraint_struct *output;
641
642 output = NULL;
643
644 i = j = k = l = -1;
645 orientation = '\0'; /* no orientation */
646 e = 0.;
647
648 ret = parse_constraints_line(line + 1, command, &i, &j, &k, &l, &loop, &orientation, &e);
649
650 if (ret == 0) {
651 /* do something with the constraint we've just read */
652
653 h = 1; /* helix length for pairs, or number of unpaired nucleotides */
654
655 /* check indices */
656 valid = 0;
657 if (i > 0) {
658 if (j == -1) {
659 /* i and range [k:l] */
660 if ((k > 0) && (l > 0)) {
661 if ((k < l) && (i < k) && (orientation == '\0')) {
662 j = i;
663 valid = 1;
664 }
665 }
666 } else if (k <= 0) {
667 /* range [i:j] and l */
668 if ((i < j) && (j < l) && (orientation == '\0')) {
669 k = l;
670 valid = 1;
671 }
672 } else if (l <= 0) {
673 /* helix of size k starting with pair (i,j), or segment [i:i+k-1] */
674 if (i != j) {
675 if ((j == 0) || (((j - i + 1) > 2 * k) && (orientation == '\0'))) {
676 h = k;
677 k = l = j;
678 j = i;
679 valid = 1;
680 }
681 }
682 } else if ((i < j) && (k < l) && (i <= k) && (j <= l) && (orientation == '\0')) {
683 /* range [i:j] and [k:l] */
684 if (command == 'P') {
685 /* we only allow this for 'prohibit pairing between two ranges' */
686 h = 0;
687 valid = 1;
688 }
689 }
690 }
691
692 if (valid) {
693 /* nucleotide constraint? */
694 if ((k == 0) && (l == 0) && (i == j) && (h > 0)) {
695 /* set correct loop type context */
696 switch (command) {
697 case 'P':
698 break;
699 case 'A': /* this case allows particular nucleotides to form non-canonical pairs */
700 loop |= VRNA_CONSTRAINT_CONTEXT_NO_REMOVE; /* do not remove possibility to stay unpaired */
701 /* fall through */
702 case 'F': /* set i == j == k == l */
703 k = l = i;
704 break;
705 case 'E':
706 loop = VRNA_CONSTRAINT_CONTEXT_ALL_LOOPS; /* soft constraints are always applied for all loops */
707 break;
708 case 'C':
709 loop |= VRNA_CONSTRAINT_CONTEXT_ENFORCE; /* enforce context dependency */
710 break;
711 default:
712 break;
713 }
714 } else {
715 /* base pair constraint */
716 /* set correct loop type context */
717 switch (command) {
718 case 'P':
719 loop = ~loop; /* prohibit */
720 loop &= VRNA_CONSTRAINT_CONTEXT_ALL_LOOPS;
721 loop |= VRNA_CONSTRAINT_CONTEXT_NO_REMOVE; /* since we prohibit pairs, we do not want to remove incompatible pairs */
722 break;
723 case 'F':
724 loop |= VRNA_CONSTRAINT_CONTEXT_ENFORCE; /* enforce */
725 break;
726 case 'E':
727 loop = VRNA_CONSTRAINT_CONTEXT_ALL_LOOPS; /* soft constraints are always applied for all loops */
728 break;
729 case 'C':
730 break; /* remove conflicting pairs only */
731 case 'A':
732 loop |= VRNA_CONSTRAINT_CONTEXT_NO_REMOVE; /* since we allow pairs, we do not want to remove incompatible pairs */
733 break;
734 default:
735 break;
736 }
737 }
738
739 output = (constraint_struct *)vrna_alloc(sizeof(constraint_struct));
740 output->command = command;
741 output->i = i;
742 output->j = j;
743 output->k = k;
744 output->l = l;
745 output->size = h;
746 output->loop = loop;
747 output->orientation = orientation;
748 output->e = e;
749 }
750 }
751
752 return (void *)output;
753 }
754
755
756 PRIVATE int
parse_constraints_line(const char * line,char command,int * i,int * j,int * k,int * l,unsigned char * loop,char * orientation,float * e)757 parse_constraints_line(const char *line,
758 char command,
759 int *i,
760 int *j,
761 int *k,
762 int *l,
763 unsigned char *loop,
764 char *orientation,
765 float *e)
766 {
767 int v1, v2;
768 int ret = 0;
769 int range_mode = 0;
770 int pos = 0;
771 int max_entries = 5;
772 int entries_seen = 0;
773 int pp;
774 float energy;
775 char buf[256], buf2[10], *c;
776 unsigned char tmp_loop;
777
778 switch (command) {
779 case 'A': /* fall through */
780 case 'F': /* fall through */
781 case 'P':
782 max_entries = 5;
783 break;
784 case 'C': /* fall through */
785 case 'E':
786 max_entries = 4;
787 break;
788 default:
789 ret = 1; /* error */
790 break;
791 }
792
793 /* default to all loop types */
794 *loop = VRNA_CONSTRAINT_CONTEXT_ALL_LOOPS;
795 tmp_loop = VRNA_CONSTRAINT_CONTEXT_NONE;
796
797 /* now lets scan the entire line for content */
798 while (!ret && (entries_seen < max_entries) &&
799 (sscanf(line + pos, "%15s%n", &buf[0], &pp) == 1)) {
800 pos += pp;
801 switch (entries_seen) {
802 case 0: /* must be i, or range */
803 if (sscanf(buf, "%d-%d%n", &v1, &v2, &pp) == 2) {
804 if (pp == strlen(buf)) {
805 *i = v1;
806 *j = v2;
807 range_mode = 1;
808 --max_entries; /* no orientation allowed now */
809 break;
810 }
811 } else if (sscanf(buf, "%d%n", &v1, &pp) == 1) {
812 if (pp == strlen(buf)) {
813 *i = v1;
814 break;
815 }
816 }
817
818 ret = 1;
819 break;
820 case 1: /* must be j, or range */
821 if (sscanf(buf, "%d-%d%n", &v1, &v2, &pp) == 2) {
822 if (pp == strlen(buf)) {
823 *k = v1;
824 *l = v2;
825 if (!range_mode)
826 --max_entries; /* no orientation allowed now */
827
828 range_mode = 1;
829 break;
830 }
831 } else if (range_mode) {
832 if (sscanf(buf, "%d%n", &v1, &pp) == 1) {
833 if (pp == strlen(buf)) {
834 *l = v1;
835 break;
836 }
837 }
838 } else if (sscanf(buf, "%d%n", &v1, &pp) == 1) {
839 if (pp == strlen(buf)) {
840 *j = v1;
841 break;
842 }
843 }
844
845 ret = 1;
846 break;
847 case 2: /* skip if in range_mode */
848 if (!range_mode) {
849 /* must be k */
850 if (sscanf(buf, "%d%n", &v1, &pp) == 1) {
851 if (pp == strlen(buf)) {
852 *k = v1;
853 break;
854 }
855 }
856
857 ret = 1;
858 break;
859 } else {
860 --max_entries;
861 /* fall through */
862 }
863
864 case 3:
865 if (command == 'E') {
866 /* must be pseudo energy */
867 if (sscanf(buf, "%g%n", &energy, &pp) == 1) {
868 if (pp == strlen(buf)) {
869 *e = energy;
870 break;
871 }
872 }
873 } else {
874 /* must be loop type, or orientation */
875 if (sscanf(buf, "%8s%n", &buf2[0], &pp) == 1) {
876 buf2[8] = '\0';
877 if (pp == strlen(buf)) {
878 for (c = &(buf2[0]); (*c != '\0') && (!ret); c++) {
879 switch (*c) {
880 case 'E':
881 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_EXT_LOOP;
882 break;
883 case 'H':
884 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_HP_LOOP;
885 break;
886 case 'I':
887 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_INT_LOOP;
888 break;
889 case 'i':
890 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_INT_LOOP_ENC;
891 break;
892 case 'M':
893 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_MB_LOOP;
894 break;
895 case 'm':
896 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_MB_LOOP_ENC;
897 break;
898 case 'A':
899 tmp_loop |= VRNA_CONSTRAINT_CONTEXT_ALL_LOOPS;
900 break;
901 case 'U':
902 case 'D':
903 *orientation = *c;
904 break;
905 default:
906 ret = 1;
907 }
908 }
909 if (tmp_loop)
910 *loop = tmp_loop;
911
912 break;
913 }
914 }
915 }
916
917 ret = 1;
918 break;
919 case 4: /* must be orientation */
920 if (!(sscanf(buf, "%c", orientation) == 1))
921 ret = 1;
922
923 break;
924 }
925 ++entries_seen;
926 }
927
928 return ret;
929 }
930