Changeset 7c3fb9b in mainline for uspace/lib/posix/src/stdio/scanf.c
- Timestamp:
- 2018-05-17T08:29:01Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6ff23ff
- Parents:
- fac0ac7
- git-author:
- Jiri Svoboda <jiri@…> (2018-05-16 17:28:17)
- git-committer:
- Jiri Svoboda <jiri@…> (2018-05-17 08:29:01)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/src/stdio/scanf.c
rfac0ac7 r7c3fb9b 61 61 _PROV_READY, 62 62 /** Cursor is temporarily lent to the external entity. No action is 63 * possible until the cursor is returned. */ 63 * possible until the cursor is returned. 64 */ 64 65 _PROV_CURSOR_LENT, 65 66 }; … … 74 75 int fetched; 75 76 /** Elements are fetched from the source in batches (e.g. by getline()) 76 * to allow using strtol/strtod family even on streams. */ 77 * to allow using strtol/strtod family even on streams. 78 */ 77 79 char *window; 78 80 /** Size of the current window. */ … … 84 86 85 87 /** Take control over data source. Finish initialization of the internal 86 * structures (e.g. allocation of window). */ 88 * structures (e.g. allocation of window). 89 */ 87 90 void (*capture)(struct __input_provider *); 88 91 /** Get a single element from the source and update the internal structures 89 92 * accordingly (e.g. greedy update of the window). Return -1 if the 90 * element cannot be obtained. */ 93 * element cannot be obtained. 94 */ 91 95 int (*pop)(struct __input_provider *); 92 96 /** Undo the most recent not-undone pop operation. Might be necesarry to 93 97 * flush current window and seek data source backwards. Return 0 if the 94 * pop history is exhausted, non-zero on success. */ 98 * pop history is exhausted, non-zero on success. 99 */ 95 100 int (*undo)(struct __input_provider *); 96 101 /** Lend the cursor to the caller. */ 97 102 const char *(*borrow_cursor)(struct __input_provider *); 98 103 /** Take control over possibly incremented cursor and update the internal 99 * structures if necessary. */ 104 * structures if necessary. 105 */ 100 106 void (*return_cursor)(struct __input_provider *, const char *); 101 107 /** Release the control over the source. That is, synchronize any 102 108 * fetched but non-consumed elements (e.g. by seeking) and destruct 103 * internal structures (e.g. window deallocation). */ 109 * internal structures (e.g. window deallocation). 110 */ 104 111 void (*release)(struct __input_provider *); 105 112 } _input_provider; … … 199 206 200 207 if (!self->cursor || self->window == self->cursor) { 201 /* Complex case. Either at EOF (cursor == NULL) or there is no more 208 /* 209 * Complex case. Either at EOF (cursor == NULL) or there is no more 202 210 * place to retreat to inside the window. Seek the source backwards 203 211 * and flush the window. Regarding the scanf, this could happend only 204 212 * when matching unbounded string (%s) or unbounded scanset (%[) not 205 213 * containing newline, while at the same time newline is the character 206 * that breaks the matching process. */ 214 * that breaks the matching process. 215 */ 207 216 int rc = fseek(self->source.stream, -1, SEEK_CUR); 208 217 if (rc == -1) { … … 292 301 assert(self->consumed >= self->fetched); 293 302 294 /* Try to correct the difference between the stream position and what was 295 * actually consumed. If it is not possible, continue anyway. */ 303 /* 304 * Try to correct the difference between the stream position and what was 305 * actually consumed. If it is not possible, continue anyway. 306 */ 296 307 fseek(self->source.stream, self->consumed - self->fetched, SEEK_CUR); 297 308 … … 412 423 return 1; 413 424 case 'p': 414 /* According to POSIX, %p modifier is implementation defined but 415 * must correspond to its printf counterpart. */ 425 /* 426 * According to POSIX, %p modifier is implementation defined but 427 * must correspond to its printf counterpart. 428 */ 416 429 case 'x': 417 430 case 'X': … … 506 519 int int_conv_base = 0; 507 520 508 /* Buffers allocated by scanf for optional 'm' specifier must be remembered 521 /* 522 * Buffers allocated by scanf for optional 'm' specifier must be remembered 509 523 * to deallocaate them in case of an error. Because each of those buffers 510 524 * corresponds to one of the argument from va_list, there is an upper bound 511 525 * on the number of those arguments. In case of C99, this uppper bound is 512 * 127 arguments. */ 526 * 127 arguments. 527 */ 513 528 char *buffers[127]; 514 529 for (int i = 0; i < 127; ++i) { … … 519 534 in->capture(in); 520 535 521 /* Interpret format string. Control shall prematurely jump from the cycle 536 /* 537 * Interpret format string. Control shall prematurely jump from the cycle 522 538 * on input failure, matching failure or illegal format string. In order 523 539 * to keep error reporting simple enough and to keep input consistent, 524 540 * error condition shall be always manifested as jump from the cycle, 525 541 * not function return. Format string pointer shall be updated specifically 526 * for each sub-case (i.e. there shall be no loop-wide increment).*/ 542 * for each sub-case (i.e. there shall be no loop-wide increment). 543 */ 527 544 while (*fmt) { 528 545 529 546 if (converting) { 530 547 531 /* Processing inside conversion specifier. Either collect optional 548 /* 549 * Processing inside conversion specifier. Either collect optional 532 550 * parameters or execute the conversion. When the conversion 533 551 * is successfully completed, increment conversion count and switch 534 * back to normal mode. */ 552 * back to normal mode. 553 */ 535 554 if (*fmt == '*') { 536 555 /* Assignment-supression (optional). */ … … 564 583 fmt = fmt_new; 565 584 } else { 566 /* Since POSIX requires width to be non-zero, it is 585 /* 586 * Since POSIX requires width to be non-zero, it is 567 587 * sufficient to interpret zero width as error without 568 * referring to errno. */ 588 * referring to errno. 589 */ 569 590 break; 570 591 } … … 572 593 /* Length modifier (optional). */ 573 594 if (length_mod == LMOD_NONE) { 574 /* Already set. Illegal format string. The actual detection 575 * is carried out in the is_length_mod(). */ 595 /* 596 * Already set. Illegal format string. The actual detection 597 * is carried out in the is_length_mod(). 598 */ 576 599 break; 577 600 } … … 590 613 } 591 614 592 /* Conversion of the integer with %p specifier needs special 615 /* 616 * Conversion of the integer with %p specifier needs special 593 617 * handling, because it is not allowed to have arbitrary 594 * length modifier. */ 618 * length modifier. 619 */ 595 620 if (*fmt == 'p') { 596 621 if (length_mod == LMOD_NONE) { … … 602 627 } 603 628 604 /* First consume any white spaces, so we can borrow cursor 629 /* 630 * First consume any white spaces, so we can borrow cursor 605 631 * from the input provider. This way, the cursor will either 606 632 * point to the non-white space while the input will be 607 633 * prefetched up to the newline (which is suitable for strtol), 608 * or the input will be at EOF. */ 634 * or the input will be at EOF. 635 */ 609 636 do { 610 637 c = in->pop(in); … … 616 643 break; 617 644 } else { 618 /* Everything is OK, just undo the last pop, so the cursor 619 * can be borrowed. */ 645 /* 646 * Everything is OK, just undo the last pop, so the cursor 647 * can be borrowed. 648 */ 620 649 in->undo(in); 621 650 } … … 626 655 const char *cur_updated = NULL; 627 656 628 /* Borrow the cursor. Until it is returned to the provider 657 /* 658 * Borrow the cursor. Until it is returned to the provider 629 659 * we cannot jump from the cycle, because it would leave 630 * the input inconsistent. */ 660 * the input inconsistent. 661 */ 631 662 cur_borrowed = in->borrow_cursor(in); 632 663 633 /* If the width is limited, the cursor horizont must be 664 /* 665 * If the width is limited, the cursor horizont must be 634 666 * decreased accordingly. Otherwise the strtol could read more 635 * than allowed by width. */ 667 * than allowed by width. 668 */ 636 669 if (width != -1) { 637 670 cur_duplicated = strndup(cur_borrowed, width); … … 661 694 cur_updated = NULL; 662 695 cur_duplicated = NULL; 663 /* Return the cursor to the provider. Input consistency is again 696 /* 697 * Return the cursor to the provider. Input consistency is again 664 698 * the job of the provider, so we can report errors from 665 * now on. */ 699 * now on. 700 */ 666 701 in->return_cursor(in, cur_borrowed); 667 702 cur_borrowed = NULL; … … 673 708 } 674 709 675 /* If not supressed, assign the converted integer into 676 * the next output argument. */ 710 /* 711 * If not supressed, assign the converted integer into 712 * the next output argument. 713 */ 677 714 if (!assign_supress) { 678 715 if (int_conv_unsigned) { … … 795 832 } 796 833 797 /* First consume any white spaces, so we can borrow cursor 834 /* 835 * First consume any white spaces, so we can borrow cursor 798 836 * from the input provider. This way, the cursor will either 799 837 * point to the non-white space while the input will be 800 838 * prefetched up to the newline (which is suitable for strtof), 801 * or the input will be at EOF. */ 839 * or the input will be at EOF. 840 */ 802 841 do { 803 842 c = in->pop(in); … … 809 848 break; 810 849 } else { 811 /* Everything is OK, just undo the last pop, so the cursor 812 * can be borrowed. */ 850 /* 851 * Everything is OK, just undo the last pop, so the cursor 852 * can be borrowed. 853 */ 813 854 in->undo(in); 814 855 } … … 819 860 const char *cur_updated = NULL; 820 861 821 /* Borrow the cursor. Until it is returned to the provider 862 /* 863 * Borrow the cursor. Until it is returned to the provider 822 864 * we cannot jump from the cycle, because it would leave 823 * the input inconsistent. */ 865 * the input inconsistent. 866 */ 824 867 cur_borrowed = in->borrow_cursor(in); 825 868 826 /* If the width is limited, the cursor horizont must be 869 /* 870 * If the width is limited, the cursor horizont must be 827 871 * decreased accordingly. Otherwise the strtof could read more 828 * than allowed by width. */ 872 * than allowed by width. 873 */ 829 874 if (width != -1) { 830 875 cur_duplicated = strndup(cur_borrowed, width); … … 862 907 cur_limited = NULL; 863 908 cur_updated = NULL; 864 /* Return the cursor to the provider. Input consistency is again 909 /* 910 * Return the cursor to the provider. Input consistency is again 865 911 * the job of the provider, so we can report errors from 866 * now on. */ 912 * now on. 913 */ 867 914 in->return_cursor(in, cur_borrowed); 868 915 cur_borrowed = NULL; … … 874 921 } 875 922 876 /* If nto supressed, assign the converted floating point number 877 * into the next output argument. */ 923 /* 924 * If nto supressed, assign the converted floating point number 925 * into the next output argument. 926 */ 878 927 if (!assign_supress) { 879 928 float *pf; … … 1008 1057 int my_buffer_idx = 0; 1009 1058 1010 /* Retrieve the buffer into which popped characters 1011 * will be stored. */ 1059 /* 1060 * Retrieve the buffer into which popped characters 1061 * will be stored. 1062 */ 1012 1063 if (!assign_supress) { 1013 1064 if (assign_alloc) { … … 1047 1098 buf_size += alloc_step; 1048 1099 } else { 1049 /* Break just from this tight loop. Errno will 1050 * be checked after it. */ 1100 /* 1101 * Break just from this tight loop. Errno will 1102 * be checked after it. 1103 */ 1051 1104 break; 1052 1105 } … … 1071 1124 /* Check for failures. */ 1072 1125 if (cur == buf) { 1073 /* Matching failure. Input failure was already checked 1074 * earlier. */ 1126 /* 1127 * Matching failure. Input failure was already checked 1128 * earlier. 1129 */ 1075 1130 matching_failure = true; 1076 1131 if (!assign_supress && assign_alloc) { … … 1128 1183 } else { 1129 1184 1130 /* Processing outside conversion specifier. Either skip white 1185 /* 1186 * Processing outside conversion specifier. Either skip white 1131 1187 * spaces or match characters one by one. If conversion specifier 1132 * is detected, switch to coversion mode. */ 1188 * is detected, switch to coversion mode. 1189 */ 1133 1190 if (isspace(*fmt)) { 1134 1191 /* Skip white spaces in the format string. */ … … 1194 1251 } 1195 1252 if (rc == EOF) { 1196 /* Caller will not know how many arguments were successfully converted, 1197 * so the deallocation of buffers is our responsibility. */ 1253 /* 1254 * Caller will not know how many arguments were successfully converted, 1255 * so the deallocation of buffers is our responsibility. 1256 */ 1198 1257 for (int i = 0; i < next_unused_buffer_idx; ++i) { 1199 1258 free(buffers[i]);
Note:
See TracChangeset
for help on using the changeset viewer.