static int _read_for (FILE* fp, int(*match)(wchar_t), wchar_t* buffer, int ret) { const wchar_t* skip = L" \n\t\r"; wchar_t c; if(buffer==NULL){ static wchar_t _buffer[1024]; buffer = _buffer; } wchar_t* cur = buffer; while(wcinrange(c=fgetwc(fp), skip)){} ungetwc(c, fp); while(!feof(fp)){ if(!match(c=fgetwc(fp))){ break; } *cur++ = c; } if(ret){ ungetwc(c, fp); } if(cur==buffer){ return 0; }else{ *cur++ = L'\0'; return 1; } }
closure *parse_number(FILE *file, closure *accum) { wchar_t c = fgetwc(file); if(iswdigit(c)){ return parse_number(file, cons(character(c), accum)); } else if(iswspace(c)) { return string_to_number(reverse(accum)); } else if(c == L')') { ungetwc(c, file); return string_to_number(reverse(accum)); } else { ungetwc(c, file); return parse_symbol(file, accum); } }
Result FStream_Unget(FStream* pfStream, wchar_t ch) { int r = ungetwc(ch, pfStream->pFile); if (r == WEOF) { } return RESULT_OK; }
JNIEXPORT jboolean JNICALL Java_mjava_io_SimpleInputStream_hasnextLine (JNIEnv * env, jobject obj) { setlocale(LC_ALL, "Chinese-simplified"); // <clocale> wchar_t ch = getwchar(); if(ch == WEOF) return 0; // 不要用EOF //if(ch == L'E') return 0; // 测试:读到E开头的字符串就退出 ungetwc(ch, stdin); return 1; }
closure *parse_symbol(FILE *file, closure *accum) { //printf("parse sym\n"); wchar_t c = fgetwc(file); if(iswspace(c)) { return string_to_symbol(reverse(accum)); } else if(c == L'\"'){ ungetwc(c, file); return string_to_symbol(reverse(accum)); } else if(c == L'('){ ungetwc(c, file); return string_to_symbol(reverse(accum)); } else if(c == L')') { ungetwc(c, file); return string_to_symbol(reverse(accum)); } else if(c == L'#'){ ungetwc(c, file); return string_to_symbol(reverse(accum)); } else { return parse_symbol(file, cons(character(c), accum)); } }
closure *parse_null(FILE *file, closure *accum) { //printf("parse null\n"); wchar_t c = fgetwc(file); if(iswspace(c)){ return parse_null(file, nil()); } else if(c == L'$'){ return parse_character(file, nil()); } else if(c == L'#'){ parse_comment(file, nil()); return parse_null(file, accum); } else if(c == L'\"'){ return parse_string(file, nil()); } else if(c == L'\''){ wchar_t c = fgetwc(file); if (!iswspace(c)){ ungetwc(c, file); closure *boo = parse_null(file, nil()); if (boo != NULL) return quote(boo); } return symbol(QUOTE); } else if(c == L'@'){ wchar_t c = fgetwc(file); if (!iswspace(c)){ ungetwc(c, file); closure *boo = parse_null(file, nil()); if (boo != NULL) return list(2, symbol(ATPEND), boo); } return symbol(ATPEND); } else if(c == L','){ wchar_t c = fgetwc(file); if (!iswspace(c)){ ungetwc(c, file); closure *boo = parse_null(file, nil()); if (boo != NULL) return list(2, symbol(COMMA), boo); } return symbol(COMMA); } else if(c == L'*'){ wchar_t c = fgetwc(file); if (!iswspace(c)){ ungetwc(c, file); closure *boo = parse_null(file, nil()); if (boo != NULL) return list(2, symbol(ASTERIX), boo); } return symbol(ASTERIX); } else if(iswdigit(c)){ ungetwc(c, file); return parse_number(file, nil()); } else if(c == L'('){ return parse_list(file, nil()); } else if(c == L')'){ ungetwc(c, file); return NULL; } else if(c == WEOF || c == EOF){ return NULL; } else { return parse_symbol(file, cons(character(c), nil())); } }
static int print(char *name) { static int notfirst = 0; char *date = NULL; char *head = NULL; int c; if (Multi != 'm' && mustopen(name, &Files[0]) == NULL) return (0); if (Multi == 'm' && Nfiles == 0 && mustopen(name, &Files[0]) == NULL) die("cannot open stdin"); if (Buffer) (void) ungetwc(Files->f_nextc, Files->f_f); if (Lnumb) Lnumb = 1; for (Page = 0; ; putpage()) { if (C == WEOF && !(fold && Buffer)) break; if (Buffer) nexbuf(); Inpos = 0; if (get(0) == WEOF) break; (void) fflush(stdout); if (++Page >= Fpage) { /* Pause if -p and not first page */ if (Ttyout && Pause && !notfirst++) { PROMPT(); /* prompt with bell and pause */ while ((c = getc(Ttyin)) != EOF && c != '\n') ; } if (Margin == 0) continue; if (date == NULL) date = GETDATE(); if (head == NULL) head = Head != NULL ? Head : Nfiles < 2 ? Files->f_name : nulls; (void) printf("\n\n"); Nspace = Offset; putspace(); (void) printf(HEAD); } } C = '\0'; return (1); }
closure *parse_list(FILE *file, closure *accum) { //printf("parse list\n"); //print_closure(accum); wchar_t c = fgetwc(file); if(c == L')'){ return reverse(accum); } else { ungetwc(c, file); closure *boo = parse_null(file, nil()); if (boo != NULL){ return parse_list(file, cons(boo, accum)); } else { return parse_list(file, accum); } } }
/* * Return a character for lexical analyser. * Only one returned character is (not enforced) legitimite. */ static void lexungetc(wint_t c) { if (c == '\n') --lineno; if (c != WEOF) { if (conptr == &context[0]) conptr = &context[NCONTEXT]; *--conptr = '\0'; } if (progfp != FNULL) { (void) ungetwc(c, progfp); return; } if (c == WEOF) return; *--progptr = c; proglen++; }
int mpq_inp_wstr10(mpq_t rop, FILE* in) { char* buf = malloc(sizeof(char)); size_t len = 1; wint_t c; for(;;) { c = fgetwc(in); if(!(iswdigit(c) || (len == 1 && c == L'-') || (c == L'/'))) break; len++; buf = realloc(buf, sizeof(char) * len); buf[len - 2] = wctob(c); } buf[len - 1] = '\0'; ungetwc(c, in); int n = mpq_set_str(rop, buf, 10); free(buf); return n; }
size_t Stream::read_line( wchar_t* buffer, size_t length, bool skip_emtpy_line ) { if( file_ == 0 ) throw Invalid_IO(); size_t count; wchar_t c = 0; do { count = 0; while( count < length && !feof( file_ ) ) { buffer[count] = c = fgetwc( file_ ); count++; if( c == '\n' ) break; if( c == '\r' ) { buffer[count - 1] = c = '\n'; if( !feof( file_ ) ) { size_t next = fgetwc( file_ ); if( next != '\n' ) ungetwc( next, file_ ); } break; } } } while( skip_emtpy_line && count == 1 && c == '\n' ); if( count < length ) buffer[count] = 0; else if( length > 0 ) buffer[length - 1] = 0; return count; }
static int do_test (void) { mtrace (); char *temp_file; TEST_VERIFY_EXIT (create_temp_file ("tst-bz22145.", &temp_file)); char buf[BUFSIZ]; { /* Check if backup buffer is correctly freed and changing back to normal buffer does not trigger an invalid free in case of static buffer set by setvbuf. */ FILE *f = fopen (temp_file, "w+b"); TEST_VERIFY_EXIT (f != NULL); TEST_VERIFY_EXIT (setvbuf (f, buf, _IOFBF, BUFSIZ) == 0); TEST_VERIFY_EXIT (ungetc ('x', f) == 'x'); TEST_VERIFY_EXIT (fseek (f, 0L, SEEK_SET) == 0); TEST_VERIFY_EXIT (fputc ('y', f) == 'y'); TEST_VERIFY_EXIT (fclose (f) == 0); } { /* Check if backup buffer is correctly freed and changing back to normal buffer does not trigger an invalid free in case of static buffer set by setvbuf. */ FILE *f = fopen (temp_file, "w+b"); TEST_VERIFY_EXIT (f != NULL); TEST_VERIFY_EXIT (setvbuf (f, buf, _IOFBF, BUFSIZ) == 0); TEST_VERIFY_EXIT (ungetc ('x', f) == 'x'); TEST_VERIFY_EXIT (fputc ('y', f) == 'y'); TEST_VERIFY_EXIT (fclose (f) == 0); } { FILE *f = fopen (temp_file, "w+b"); TEST_VERIFY_EXIT (f != NULL); TEST_VERIFY_EXIT (setvbuf (f, buf, _IOFBF, BUFSIZ) == 0); TEST_VERIFY_EXIT (ungetwc (L'x', f) == L'x'); TEST_VERIFY_EXIT (fseek (f, 0L, SEEK_SET) == 0); TEST_VERIFY_EXIT (fputwc (L'y', f) == L'y'); TEST_VERIFY_EXIT (fclose (f) == 0); } { FILE *f = fopen (temp_file, "w+b"); TEST_VERIFY_EXIT (f != NULL); TEST_VERIFY_EXIT (setvbuf (f, buf, _IOFBF, BUFSIZ) == 0); TEST_VERIFY_EXIT (ungetwc (L'x', f) == L'x'); TEST_VERIFY_EXIT (fputwc (L'y', f) == L'y'); TEST_VERIFY_EXIT (fclose (f) == 0); } free (temp_file); return 0; }
char *u8fgets(char *buf, int len, FILE *file) { wint_t c, c0; wchar_t ws[2 + 1]; char *b, *dst = NULL; if(file == stdin) { if(buf == NULL || len <= 0) return NULL; buf[0] = '\0'; c0 = L'\0'; while((c = fgetwc(file)) != WEOF) { if(IS_HIGH_SURROGATE(c0)) { if(IS_LOW_SURROGATE(c)) { ws[0] = c0; ws[1] = c; ws[2] = L'\0'; } else { ungetwc(c, file); ws[0] = c0; ws[1] = L'\0'; } } else if(IS_HIGH_SURROGATE(c)) { c0 = c; continue; } else { ws[0] = c; ws[1] = L'\0'; } c0 = L'\0'; b = u8wstos(ws); if(b) { if(len > (int)(strlen(buf) + strlen(b))) { strcat(buf, b); free(b); } else { free(b); if(ws[1] != L'\0') ungetwc(ws[1], file); if(ws[0] != L'\0') ungetwc(ws[0], file); break; } } if(c == L'\n') break; } if(c0 != L'\0') { ungetwc(c0, file); } if(strlen(buf) > 0) dst = buf; } else { dst = fgets(buf, len, file); } return dst; }
int main() { mbstate_t mb = {0}; size_t s = 0; tm tm = {0}; wint_t w = 0; ::FILE* fp = 0; __darwin_va_list va; char* ns = 0; wchar_t* ws = 0; static_assert((std::is_same<decltype(fwprintf(fp, L"")), int>::value), ""); static_assert((std::is_same<decltype(fwscanf(fp, L"")), int>::value), ""); static_assert((std::is_same<decltype(swprintf(ws, s, L"")), int>::value), ""); static_assert((std::is_same<decltype(swscanf(L"", L"")), int>::value), ""); static_assert((std::is_same<decltype(vfwprintf(fp, L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vfwscanf(fp, L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vswprintf(ws, s, L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vswscanf(L"", L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vwprintf(L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vwscanf(L"", va)), int>::value), ""); static_assert((std::is_same<decltype(wprintf(L"")), int>::value), ""); static_assert((std::is_same<decltype(wscanf(L"")), int>::value), ""); static_assert((std::is_same<decltype(fgetwc(fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(fgetws(ws, 0, fp)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(fputwc(L' ', fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(fputws(L"", fp)), int>::value), ""); static_assert((std::is_same<decltype(fwide(fp, 0)), int>::value), ""); static_assert((std::is_same<decltype(getwc(fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(getwchar()), wint_t>::value), ""); static_assert((std::is_same<decltype(putwc(L' ', fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(putwchar(L' ')), wint_t>::value), ""); static_assert((std::is_same<decltype(ungetwc(L' ', fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(wcstod(L"", (wchar_t**)0)), double>::value), ""); static_assert((std::is_same<decltype(wcstof(L"", (wchar_t**)0)), float>::value), ""); static_assert((std::is_same<decltype(wcstold(L"", (wchar_t**)0)), long double>::value), ""); static_assert((std::is_same<decltype(wcstol(L"", (wchar_t**)0, 0)), long>::value), ""); static_assert((std::is_same<decltype(wcstoll(L"", (wchar_t**)0, 0)), long long>::value), ""); static_assert((std::is_same<decltype(wcstoul(L"", (wchar_t**)0, 0)), unsigned long>::value), ""); static_assert((std::is_same<decltype(wcstoull(L"", (wchar_t**)0, 0)), unsigned long long>::value), ""); static_assert((std::is_same<decltype(wcscpy(ws, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsncpy(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcscat(ws, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsncat(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcscmp(L"", L"")), int>::value), ""); static_assert((std::is_same<decltype(wcscoll(L"", L"")), int>::value), ""); static_assert((std::is_same<decltype(wcsncmp(L"", L"", s)), int>::value), ""); static_assert((std::is_same<decltype(wcsxfrm(ws, L"", s)), size_t>::value), ""); static_assert((std::is_same<decltype(wcschr((wchar_t*)0, L' ')), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcscspn(L"", L"")), size_t>::value), ""); static_assert((std::is_same<decltype(wcslen(L"")), size_t>::value), ""); static_assert((std::is_same<decltype(wcspbrk((wchar_t*)0, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsrchr((wchar_t*)0, L' ')), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsspn(L"", L"")), size_t>::value), ""); static_assert((std::is_same<decltype(wcsstr((wchar_t*)0, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcstok(ws, L"", (wchar_t**)0)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemchr((wchar_t*)0, L' ', s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemcmp(L"", L"", s)), int>::value), ""); static_assert((std::is_same<decltype(wmemcpy(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemmove(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemset(ws, L' ', s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsftime(ws, s, L"", &tm)), size_t>::value), ""); static_assert((std::is_same<decltype(btowc(0)), wint_t>::value), ""); static_assert((std::is_same<decltype(wctob(w)), int>::value), ""); static_assert((std::is_same<decltype(mbsinit(&mb)), int>::value), ""); static_assert((std::is_same<decltype(mbrlen("", s, &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(mbrtowc(ws, "", s, &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(wcrtomb(ns, L' ', &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(mbsrtowcs(ws, (const char**)0, s, &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(wcsrtombs(ns, (const wchar_t**)0, s, &mb)), size_t>::value), ""); }
/** * Tests the communicator console input. */ void test_communicator_console_input() { log_write_terminated_message((void*) stdout, L"Test communicator console input:\n"); #ifdef GNU_LINUX_OPERATING_SYSTEM // The terminal device name. FILE* t = (FILE*) *NULL_POINTER_MEMORY_MODEL; // The old termios settings. struct termios* to = (struct termios*) *NULL_POINTER_MEMORY_MODEL; // The new termios settings. struct termios* tn = (struct termios*) *NULL_POINTER_MEMORY_MODEL; // Allocate gnu/linux console internals. to = (struct termios*) malloc(*INPUT_OUTPUT_SYSTEM_TERMINAL_TYPE_SIZE); tn = (struct termios*) malloc(*INPUT_OUTPUT_SYSTEM_TERMINAL_TYPE_SIZE); // Set file stream. t = stdin; // Get file descriptor for file stream. // CAUTION! The stream "stdin" must be used instead of "stdout" here! int d = fileno(t); // Test standard streams. int testin = fileno(stdin); int testout = fileno(stdout); int testerr = fileno(stderr); fwprintf(stdout, L"TEST in %i\n", testin); fwprintf(stdout, L"TEST out %i\n", testout); fwprintf(stdout, L"TEST err %i\n", testerr); // Store old termios settings. int e = tcgetattr(d, (void*) to); if (e != *NUMBER_MINUS_1_INTEGER_MEMORY_MODEL) { // Initialise new termios settings. *tn = *to; // Manipulate termios attributes. // Set number of characters. tn->c_cc[VMIN] = *NUMBER_1_INTEGER_MEMORY_MODEL; tn->c_cc[VTIME] = *NUMBER_0_INTEGER_MEMORY_MODEL; tn->c_lflag &= ~ICANON; // Switch off echo. tn->c_lflag &= ~ECHO; // Set new termios attributes. tcsetattr(d, TCSANOW, (void*) tn); wint_t c = fgetwc(t); fwprintf(stdout, L"TEST c: %i\n", c); ungetwc(c, t); fwprintf(stdout, L"TEST unget c: %i\n", c); wint_t again = fgetwc(t); fwprintf(stdout, L"TEST again c: %i\n", again); // Reset terminal to old settings. tcsetattr(d, TCSANOW, (void*) to); } else { if (errno == EBADF) { log_write_terminated_message((void*) stdout, L"Could not store old termios settings. The filedes argument is not a valid file descriptor.\n"); } else if (errno == ENOTTY) { log_write_terminated_message((void*) stdout, L"Could not store old termios settings. The filedes is not associated with a terminal.\n"); } else { log_write_terminated_message((void*) stdout, L"Could not store old termios settings.\n"); } } // GNU_LINUX_OPERATING_SYSTEM #endif }
LISPTR lisp_read(FILE* in) { LISPTR s = NIL; wchar_t ch = fgetwc(in); while (iswspace(ch)) { ch = fgetwc(in); } if (ch == '(') { // start of cons LISPTR last = s = cons(lisp_read(in), NIL); while (true) { ch = fgetwc(in); while (iswspace(ch)) { ch = fgetwc(in); } if (ch==WEOF || ch==')') { break; } ungetwc(ch, in); LISPTR e = lisp_read(in); rplacd(last, cons(e, NIL)); last = cdr(last); } } else if (ch == '\'') { // '<expr>, sugar for (QUOTE <expr>) s = cons(QUOTE, cons(lisp_read(in), NIL)); } else if (ch == '#') { // so-called sharpsign or 'dispatching macro character' // http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.htm ch = fgetwc(in); switch (ch) { case '\'': // function-quote s = cons(FUNCTION, cons(lisp_read(in), NIL)); break; default: lisp_error(L"invalid char after #"); break; } // switch } else if (ch == WEOF) { // end of file, return NIL. } else { // must be an atom - number, symbol or string wchar_t name[MAX_ATOM_CHARS]; int n = 0; while (true) { if (n < MAX_ATOM_CHARS) { name[n++] = towupper(ch); } ch = fgetwc(in); if (ch==WEOF) break; // better not be inside a string, eh? if (name[0] != '"') { // not a string if (iswspace(ch)) break; if (ch==')' || ch=='(') { ungetwc(ch, in); break; } } else { // collecting a string if (ch=='\\') { ch = fgetwc(in); if (ch==WEOF) break; // bad luck er bad string syntax } else if (ch=='"') { break; // end of string } } } // while (true) name[n] = 0; if (name[0] == '"') { s = intern_string(name+1); } else if (isnumber(name)) { s = intern_number(name); } else { s = intern(name); } } return s; }
/** * Senses gnu/linux console message. * * @param p0 the interrupt * @param p1 the mutex * @param p2 the sleep time * @param p3 the input stream */ void communicate_sensing_gnu_linux_console_message(void* p0, void* p1, void* p2, void* p3) { if (p3 != *NULL_POINTER_MEMORY_MODEL) { FILE* is = (FILE*) p3; if (p2 != *NULL_POINTER_MEMORY_MODEL) { double* st = (double*) p2; if (p1 != *NULL_POINTER_MEMORY_MODEL) { pthread_mutex_t* mt = (pthread_mutex_t*) p1; if (p0 != *NULL_POINTER_MEMORY_MODEL) { int* irq = (int*) p0; // CAUTION! DO NOT log this function call! // This function is executed within a thread, but the // logging is not guaranteed to be thread-safe and might // cause unpredictable programme behaviour. // Also, this function runs in an endless loop and would produce huge log files. // log_terminated_message((void*) DEBUG_LEVEL_LOG_MODEL, (void*) L"Sense gnu/linux console message."); // Lock gnu/linux console mutex. // // CAUTION! This lock has to stand not only before the interrupt request is set below, // BUT ALSO BEFORE the next character is detected in the input stream! // // This is because the main thread might be reading characters from the // input stream right now in parallel, while this thread tries to read as well. // // This was tested out and lead to errors, because the "ungetwc" function below // was unexpectedly putting back a character such as ^ (escape) or [ // which (in the case of escape) caused the programme to exit // and other inputs like arrow down not to be recognised properly. pthread_mutex_lock(mt); // Get character from gnu/linux console input stream, // just to detect that some (event) character is available. // This is also called "peeking ahead" at the input. // // CAUTION! Use 'wint_t' instead of 'int' as return type for // 'getwchar()', since that returns 'WEOF' instead of 'EOF'! wint_t c = fgetwc(is); if (c == WEOF) { // No valid character was returned. // Sleep for some time. // This is to give the central processing unit (cpu) some // time to breathe, that is to be idle or to process other signals. sleep(*st); } else { // Unread character, that is push it back on the stream to // make it available to be input again from the stream, by the // next call to fgetc or another input function on that stream. // // If c is EOF, ungetc does nothing and just returns EOF. // This lets you call ungetc with the return value of getc // without needing to check for an error from getc. // // The character that you push back doesn't have to be the same // as the last character that was actually read from the stream. // In fact, it isn't necessary to actually read any characters // from the stream before unreading them with ungetc! // But that is a strange way to write a program; // usually ungetc is used only to unread a character that was // just read from the same stream. // // The GNU C library only supports one character of pushback. // In other words, it does not work to call ungetc twice without // doing input in between. // Other systems might let you push back multiple characters; // then reading from the stream retrieves the characters in the // reverse order that they were pushed. // // Pushing back characters doesn't alter the file; // only the internal buffering for the stream is affected. // If a file positioning function (such as fseek, fseeko or rewind) // is called, any pending pushed-back characters are discarded. // // Unreading a character on a stream that is at end of file // clears the end-of-file indicator for the stream, because it // makes the character of input available. // After you read that character, trying to read again will // encounter end of file. ungetwc(c, is); // Set gnu/linux console interrupt request to indicate // that a message has been received via gnu/linux console, // which may now be processed in the main thread of this system. *irq = *NUMBER_1_INTEGER_MEMORY_MODEL; } // Unlock gnu/linux console mutex. pthread_mutex_unlock(mt); while (*irq != *NUMBER_0_INTEGER_MEMORY_MODEL) { // Sleep as long as the gnu/linux console interrupt is not handled and reset yet. // // This is to give the central processing unit (cpu) some // time to breathe, that is to be idle or to process other signals. // // Also, many character inputs are processed at once in the main thread // and only if there are no further characters to be read, the irq flag is reset, // so that this endless loop can be left and new inputs detected. sleep(*st); } } else { // CAUTION! DO NOT log this function call! // This function is executed within a thread, but the // logging is not guaranteed to be thread-safe and might // cause unpredictable programme behaviour. // log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not sense gnu/linux console message. The interrupt is null."); } } else { // CAUTION! DO NOT log this function call! // This function is executed within a thread, but the // logging is not guaranteed to be thread-safe and might // cause unpredictable programme behaviour. // log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not sense gnu/linux console message. The mutex is null."); } } else { // CAUTION! DO NOT log this function call! // This function is executed within a thread, but the // logging is not guaranteed to be thread-safe and might // cause unpredictable programme behaviour. // log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not sense gnu/linux console message. The sleep time is null."); } } else { // CAUTION! DO NOT log this function call! // This function is executed within a thread, but the // logging is not guaranteed to be thread-safe and might // cause unpredictable programme behaviour. // log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not sense gnu/linux console message. The input stream is null."); } }
static void putspace(void) { int nc = 0; for (; Nspace > 0; Outpos += nc, Nspace -= nc) { #ifdef XPG4 /* XPG4: -i: replace multiple SPACE chars with tab chars */ if ((Nspace >= 2 && Itabn > 0 && Nspace >= (nc = Itabn - Outpos % Itabn)) && !fold) { #else /* Solaris: -i: replace white space with tab chars */ if ((Itabn > 0 && Nspace >= (nc = Itabn - Outpos % Itabn)) && !fold) { #endif (void) fputwc(Itabc, stdout); } else { nc = 1; (void) putchar(' '); } } } static void unget(int colno) { if (Buffer) { if (*(Colpts[colno].c_ptr-1) != '\t') --(Colpts[colno].c_ptr); if (Colpts[colno].c_lno) Colpts[colno].c_lno--; } else { if ((Multi == 'm' && colno == 0) || Multi != 'm') if (Lnumb && !foldcol) Lnumb--; colno = (Multi == 'a') ? 0 : colno; (void) ungetwc(Files[colno].f_nextc, Files[colno].f_f); Files[colno].f_nextc = C; } } /* * Defer message about failure to open file to prevent messing up * alignment of page with tear perforations or form markers. * Treat empty file as special case and report as diagnostic. */ static FILE * mustopen(char *s, FILS *f) { char *empty_file_msg = gettext("%s -- empty file"); int c; if (*s == '\0') { f->f_name = STDINNAME(); f->f_f = stdin; } else if ((f->f_f = fopen(f->f_name = s, "r")) == NULL) { s = ffiler(f->f_name); s = strcpy((char *)getspace((UNS) strlen(s) + 1), s); } if (f->f_f != NULL) { errno = 0; f->f_nextc = _fgetwc_pr(f->f_f, &c); if (f->f_nextc != WEOF) { return (f->f_f); } else { /* WEOF */ if (errno == EILSEQ) { f->f_nextc = (wchar_t)c; return (f->f_f); } if (Multi == 'm') return (f->f_f); } (void) sprintf(s = (char *)getspace((UNS) strlen(f->f_name) + 1 + (UNS) strlen(empty_file_msg)), empty_file_msg, f->f_name); (void) fclose(f->f_f); } Error = 1; if (Report) if (Ttyout) { /* accumulate error reports */ Lasterr = Lasterr->e_nextp = (ERR *) getspace((UNS) sizeof (ERR)); Lasterr->e_nextp = NULL; Lasterr->e_mess = s; } else { /* ok to print error report now */ cerror(s); (void) putc('\n', stderr); } return ((FILE *)NULL); }
static int do_test (void) { size_t i; wint_t wc; FILE *fp; int fd; fname = (char *) malloc (strlen (test_dir) + sizeof "/bug-ungetwc2.XXXXXX"); if (fname == NULL) { puts ("no memory"); return 1; } strcpy (stpcpy (fname, test_dir), "/bug-ungetwc2.XXXXXX"); fd = mkstemp (fname); if (fd == -1) { printf ("cannot open temporary file: %m\n"); return 1; } add_temp_file (fname); printf ("\nNote: This program runs on %s locale.\n\n", test_locale); if (setlocale (LC_ALL, test_locale) == NULL) { fprintf (stderr, "Cannot use `%s' locale.\n", test_locale); exit (EXIT_FAILURE); } /* Output to the file. */ if ((fp = fdopen (fd, "w")) == NULL) { setlocale (LC_ALL, "C"); fprintf (stderr, "Cannot make `%s' file.\n", fname); exit (EXIT_FAILURE); } fprintf (fp, "%ls", write_wchars); fclose (fp); /* Read from the file. */ fp = fopen (fname, "r"); if (fp == NULL) { setlocale (LC_ALL, "C"); error (EXIT_FAILURE, errno, "cannot open %s", fname); } printf ("%s is opened.\n", fname); for (i = 0; i < last_pos; i++) { wc = getwc (fp); printf ("> `%lc' is gotten.\n", wc); } /* Unget a wide character. */ ungetwc (unget_wchar, fp); printf ("< `%lc' is ungotten.\n", unget_wchar); /* Reget the wide character. */ wc = getwc (fp); printf ("> `%lc' is regotten.\n", wc); fflush (stdout); fclose (fp); return 0; }
int main (void) { FILE *fp; const char *str = "abcdef"; wint_t ret, wc, ungetone = 0x00E4; /* 0x00E4 means `a umlaut'. */ char fname[] = "/tmp/tst-ungetwc1.out.XXXXXX"; int fd; int result = 0; puts ("This program runs on de_DE.UTF-8 locale."); if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL) { fprintf (stderr, "Err: Cannot run on the de_DE.UTF-8 locale"); exit (EXIT_FAILURE); } fd = mkstemp (fname); if (fd == -1) { printf ("cannot open temp file: %m\n"); exit (EXIT_FAILURE); } /* Write some characters to `testfile'. */ if ((fp = fdopen (fd, "w")) == NULL) { fprintf (stderr, "Cannot open 'testfile'."); exit (EXIT_FAILURE); } fputs (str, fp); fclose (fp); /* Open `testfile'. */ if ((fp = fopen (fname, "r")) == NULL) { fprintf (stderr, "Cannot open 'testfile'."); exit (EXIT_FAILURE); } /* Unget a character. */ ret = ungetwc (ungetone, fp); printf ("Unget a character (0x%04x)\n", (unsigned int) ungetone); fflush (stdout); if (ret == WEOF) { puts ("ungetwc() returns NULL."); exit (EXIT_SUCCESS); } /* Reget a character. */ wc = getwc (fp); printf ("Reget a character (0x%04x)\n", (unsigned int) wc); fflush (stdout); if (wc == ungetone) { puts ("The ungotten character is equal to the regotten character."); fflush (stdout); } else { puts ("The ungotten character is not equal to the regotten character."); printf ("ungotten one: %04x, regetone: %04x", ungetone, wc); fflush (stdout); result = 1; } fclose (fp); unlink (fname); return result; }
/** * Receives a gnu/linux console character. * * @param p0 the destination wide character array (Hand over as reference!) * @param p1 the destination wide character array count * @param p2 the destination wide character array size * @param p3 the loop break flag * @param p4 the input character * @param p5 the escape character mode * @param p6 the escape control sequence mode * @param p7 the source input stream * @param p8 the mutex */ void receive_gnu_linux_console_character(void* p0, void* p1, void* p2, void* p3, void* p4, void* p5, void* p6, void* p7, void* p8) { if (p7 != *NULL_POINTER_MEMORY_MODEL) { FILE* s = (FILE*) p7; if (p6 != *NULL_POINTER_MEMORY_MODEL) { int* csi = (int*) p6; if (p5 != *NULL_POINTER_MEMORY_MODEL) { int* esc = (int*) p5; if (p4 != *NULL_POINTER_MEMORY_MODEL) { wint_t* c = (wint_t*) p4; if (p3 != *NULL_POINTER_MEMORY_MODEL) { int* b = (int*) p3; log_terminated_message((void*) DEBUG_LEVEL_LOG_MODEL, (void*) L"Receive gnu/linux console character."); // Initialise error number. // It is a global variable/ function and other operations // may have set some value that is not wanted here. // // CAUTION! Initialise the error number BEFORE calling // the function that might cause an error. errno = *NUMBER_0_INTEGER_MEMORY_MODEL; // Lock gnu/linux console mutex. pthread_mutex_lock(p8); // Receive character from source input stream of gnu/linux console. // // CAUTION! The multibyte- is converted to a wide character internally, // so that the return value of type "wint_t" may be casted to "wchar_t". // Function calls to "decode_utf_8_unicode_character_vector" are therefore NOT necessary here! *c = fgetwc(s); // Unlock gnu/linux console mutex. pthread_mutex_unlock(p8); if (errno != EILSEQ) { if (*csi == *NUMBER_1_INTEGER_MEMORY_MODEL) { // Reset escape control sequence flag. *csi = *NUMBER_0_INTEGER_MEMORY_MODEL; // Copy source character to destination character array. overwrite_array(p0, p4, (void*) WIDE_CHARACTER_PRIMITIVE_MEMORY_ABSTRACTION, (void*) PRIMITIVE_MEMORY_MODEL_COUNT, p1, (void*) VALUE_PRIMITIVE_MEMORY_NAME, p1, p2); // Set loop break flag. // An escape character followed by a left square bracket character // were received before. So this is an escape control sequence. // Since all values have been received, the loop can be left now. *b = *NUMBER_1_INTEGER_MEMORY_MODEL; } else if (*esc == *NUMBER_1_INTEGER_MEMORY_MODEL) { // Reset escape character flag. *esc = *NUMBER_0_INTEGER_MEMORY_MODEL; // An escape character was received before. if (*c == *((wint_t*) LEFT_SQUARE_BRACKET_UNICODE_CHARACTER_CODE_MODEL)) { // The escape character received before is followed by an opening square bracket, // which means that this is the start of an escape control sequence. // Set escape control sequence flag. *csi = *NUMBER_1_INTEGER_MEMORY_MODEL; // Copy source character to destination character array. overwrite_array(p0, p4, (void*) WIDE_CHARACTER_PRIMITIVE_MEMORY_ABSTRACTION, (void*) PRIMITIVE_MEMORY_MODEL_COUNT, p1, (void*) VALUE_PRIMITIVE_MEMORY_NAME, p1, p2); } else { // This is NOT going to be an escape control sequence. // An escape- followed by another, second character // (which is not an opening square bracket) has been detected. // Lock gnu/linux console mutex. pthread_mutex_lock(p8); // Unget this character so that it may be processed once more later on. ungetwc(*c, p7); // Unlock gnu/linux console mutex. pthread_mutex_unlock(p8); // Set loop break flag. *b = *NUMBER_1_INTEGER_MEMORY_MODEL; } } else if (*c == *((wint_t*) ESCAPE_CONTROL_UNICODE_CHARACTER_CODE_MODEL)) { // Set escape character flag. *esc = *NUMBER_1_INTEGER_MEMORY_MODEL; // Copy source character to destination character array. overwrite_array(p0, p4, (void*) WIDE_CHARACTER_PRIMITIVE_MEMORY_ABSTRACTION, (void*) PRIMITIVE_MEMORY_MODEL_COUNT, p1, (void*) VALUE_PRIMITIVE_MEMORY_NAME, p1, p2); } else if (*c == WEOF) { // The function "communicate_sensing_gnu_linux_console_message" filters out // invalid (non-existing) characters recognised by the return value WEOF (-1). // However, to be on the safe side, they are filtered out here once more. // Set loop break flag. *b = *NUMBER_1_INTEGER_MEMORY_MODEL; } else { // Copy source character to destination character array. overwrite_array(p0, p4, (void*) WIDE_CHARACTER_PRIMITIVE_MEMORY_ABSTRACTION, (void*) PRIMITIVE_MEMORY_MODEL_COUNT, p1, (void*) VALUE_PRIMITIVE_MEMORY_NAME, p1, p2); // Set loop break flag. *b = *NUMBER_1_INTEGER_MEMORY_MODEL; } } else { log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not receive from gnu/linux console. The character reading failed."); // Set loop break flag. *b = *NUMBER_1_INTEGER_MEMORY_MODEL; } } else { log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not receive gnu/linux console character. The loop break flag is null."); } } else { log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not receive gnu/linux console character. The input character is null."); } } else { log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not receive gnu/linux console character. The escape character mode is null."); } } else { log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not receive gnu/linux console character. The escape control sequence is null."); } } else { log_terminated_message((void*) ERROR_LEVEL_LOG_MODEL, (void*) L"Could not receive gnu/linux console character. The source input stream is null."); } }
int main() { // mbstate_t comes from the underlying C library; it is defined (in C99) as: // a complete object type other than an array type that can hold the conversion // state information necessary to convert between sequences of multibyte // characters and wide characters #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-braces" #endif mbstate_t mb = {0}; #if defined(__clang__) #pragma clang diagnostic pop #endif size_t s = 0; tm *tm = 0; wint_t w = 0; ::FILE* fp = 0; #ifdef __APPLE__ __darwin_va_list va; #else __builtin_va_list va; #endif char* ns = 0; wchar_t* ws = 0; static_assert((std::is_same<decltype(fwprintf(fp, L"")), int>::value), ""); static_assert((std::is_same<decltype(fwscanf(fp, L"")), int>::value), ""); static_assert((std::is_same<decltype(swprintf(ws, s, L"")), int>::value), ""); static_assert((std::is_same<decltype(swscanf(L"", L"")), int>::value), ""); static_assert((std::is_same<decltype(vfwprintf(fp, L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vfwscanf(fp, L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vswprintf(ws, s, L"", va)), int>::value), ""); static_assert((std::is_same<decltype(vswscanf(L"", L"", va)), int>::value), ""); static_assert((std::is_same<decltype(fgetwc(fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(fgetws(ws, 0, fp)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(fputwc(L' ', fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(fputws(L"", fp)), int>::value), ""); static_assert((std::is_same<decltype(fwide(fp, 0)), int>::value), ""); static_assert((std::is_same<decltype(getwc(fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(putwc(L' ', fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(ungetwc(L' ', fp)), wint_t>::value), ""); static_assert((std::is_same<decltype(wcstod(L"", (wchar_t**)0)), double>::value), ""); static_assert((std::is_same<decltype(wcstof(L"", (wchar_t**)0)), float>::value), ""); static_assert((std::is_same<decltype(wcstold(L"", (wchar_t**)0)), long double>::value), ""); static_assert((std::is_same<decltype(wcstol(L"", (wchar_t**)0, 0)), long>::value), ""); static_assert((std::is_same<decltype(wcstoll(L"", (wchar_t**)0, 0)), long long>::value), ""); static_assert((std::is_same<decltype(wcstoul(L"", (wchar_t**)0, 0)), unsigned long>::value), ""); static_assert((std::is_same<decltype(wcstoull(L"", (wchar_t**)0, 0)), unsigned long long>::value), ""); static_assert((std::is_same<decltype(wcscpy(ws, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsncpy(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcscat(ws, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsncat(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcscmp(L"", L"")), int>::value), ""); static_assert((std::is_same<decltype(wcscoll(L"", L"")), int>::value), ""); static_assert((std::is_same<decltype(wcsncmp(L"", L"", s)), int>::value), ""); static_assert((std::is_same<decltype(wcsxfrm(ws, L"", s)), size_t>::value), ""); static_assert((std::is_same<decltype(wcschr((wchar_t*)0, L' ')), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcscspn(L"", L"")), size_t>::value), ""); static_assert((std::is_same<decltype(wcslen(L"")), size_t>::value), ""); static_assert((std::is_same<decltype(wcspbrk((wchar_t*)0, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsrchr((wchar_t*)0, L' ')), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsspn(L"", L"")), size_t>::value), ""); static_assert((std::is_same<decltype(wcsstr((wchar_t*)0, L"")), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcstok(ws, L"", (wchar_t**)0)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemchr((wchar_t*)0, L' ', s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemcmp(L"", L"", s)), int>::value), ""); static_assert((std::is_same<decltype(wmemcpy(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemmove(ws, L"", s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemset(ws, L' ', s)), wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsftime(ws, s, L"", tm)), size_t>::value), ""); static_assert((std::is_same<decltype(btowc(0)), wint_t>::value), ""); static_assert((std::is_same<decltype(wctob(w)), int>::value), ""); static_assert((std::is_same<decltype(mbsinit(&mb)), int>::value), ""); static_assert((std::is_same<decltype(mbrlen("", s, &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(mbrtowc(ws, "", s, &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(wcrtomb(ns, L' ', &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(mbsrtowcs(ws, (const char**)0, s, &mb)), size_t>::value), ""); static_assert((std::is_same<decltype(wcsrtombs(ns, (const wchar_t**)0, s, &mb)), size_t>::value), ""); // These tests fail on systems whose C library doesn't provide a correct overload // set for wcschr, wcspbrk, wcsrchr, wcsstr, and wmemchr, unless the compiler is // a suitably recent version of Clang. #if !defined(__APPLE__) || defined(_LIBCPP_PREFERRED_OVERLOAD) static_assert((std::is_same<decltype(wcschr((const wchar_t*)0, L' ')), const wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcspbrk((const wchar_t*)0, L"")), const wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsrchr((const wchar_t*)0, L' ')), const wchar_t*>::value), ""); static_assert((std::is_same<decltype(wcsstr((const wchar_t*)0, L"")), const wchar_t*>::value), ""); static_assert((std::is_same<decltype(wmemchr((const wchar_t*)0, L' ', s)), const wchar_t*>::value), ""); #endif #ifndef _LIBCPP_HAS_NO_STDIN static_assert((std::is_same<decltype(getwchar()), wint_t>::value), ""); static_assert((std::is_same<decltype(vwscanf(L"", va)), int>::value), ""); static_assert((std::is_same<decltype(wscanf(L"")), int>::value), ""); #endif #ifndef _LIBCPP_HAS_NO_STDOUT static_assert((std::is_same<decltype(putwchar(L' ')), wint_t>::value), ""); static_assert((std::is_same<decltype(vwprintf(L"", va)), int>::value), ""); static_assert((std::is_same<decltype(wprintf(L"")), int>::value), ""); #endif }