<commit_before>// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/reent.h>
#include <stdlib.h>
#include "esp_attr.h"
#include "rom/libc_stubs.h"
#include "rom/uart.h"
#include "soc/cpu.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"

void abort() {
    do
    {
        __asm__ ("break 0,0");
        *((int*) 0) = 0;
    } while(true);
}

void* _malloc_r(struct _reent *r, size_t size) {
    return pvPortMalloc(size);
}

void _free_r(struct _reent *r, void* ptr) {
    return vPortFree(ptr);
}

void* _realloc_r(struct _reent *r, void* ptr, size_t size) {
	void* new_chunk;
	if (size == 0) {
		if (ptr) {
			vPortFree(ptr);
		}
		return NULL;
	}

	new_chunk = pvPortMalloc(size);
	if (new_chunk && ptr) {
		memcpy(new_chunk, ptr, size);
		vPortFree(ptr);
	}
	// realloc behaviour: don't free original chunk if alloc failed
	return new_chunk;
}

void* _calloc_r(struct _reent *r, size_t count, size_t size) {
    void* result = pvPortMalloc(count * size);
    if (result)
    {
    	memset(result, 0, count * size);
    }
    return result;
}

int _system_r(struct _reent *r, const char *str) {
    abort();
    return 0;
}

int _rename_r(struct _reent *r, const char *src, const char *dst) {
    abort();
    return 0;
}

clock_t _times_r(struct _reent *r, struct tms *ptms) {
    abort();
    return 0;
}

// TODO: read time from RTC
int _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) {
    abort();
    return 0;
}

void _raise_r(struct _reent *r) {
    abort();
}

int _unlink_r(struct _reent *r, const char *path) {
    abort();
    return 0;
}

int _link_r(struct _reent *r, const char* n1, const char* n2) {
    abort();
    return 0;
}

int _stat_r(struct _reent *r, const char * path, struct stat * st) {
    return 0;
}

int _fstat_r(struct _reent *r, int fd, struct stat * st) {
	st->st_mode = S_IFCHR;
    return 0;
}

void* _sbrk_r(struct _reent *r, ptrdiff_t sz) {
    abort();
    return 0;
}

int _getpid_r(struct _reent *r) {
    abort();
    return 0;
}

int _kill_r(struct _reent *r, int pid, int sig) {
    abort();
    return 0;
}

void _exit_r(struct _reent *r, int e) {
    abort();
}

int _close_r(struct _reent *r, int fd) {
    return 0;
}

int _open_r(struct _reent *r, const char * path, int flags, int mode) {
    return 0;
}

ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) {
    const char* p = (const char*) data;
    if (fd == STDOUT_FILENO) {
        static _lock_t stdout_lock; /* lazily initialised */
        /* Even though newlib does stream locking on stdout, we need
           a dedicated stdout UART lock...

           This is because each task has its own _reent structure with
           unique FILEs for stdin/stdout/stderr, so these are
           per-thread (lazily initialised by __sinit the first time a
           stdio function is used, see findfp.c:235.

           It seems like overkill to allocate a FILE-per-task and lock
           a thread-local stream, but I see no easy way to fix this
           (pre-__sinit_, tasks have "fake" FILEs ie __sf_fake_stdout
           which aren't fully valid.)
        */
        _lock_acquire_recursive(&stdout_lock);
        while(size--) {
#if CONFIG_NEWLIB_STDOUT_ADDCR
            if (*p=='\n') {
                uart_tx_one_char('\r');
            }
#endif
            uart_tx_one_char(*p);
            ++p;
        }
        _lock_release_recursive(&stdout_lock);
    }
    return size;
}

_off_t _lseek_r(struct _reent *r, int fd, _off_t size, int mode) {
    return 0;
}

// TODO: implement reading from UART
ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size) {
    return 0;
}

/* Notes on our newlib lock implementation:
 *
 * - Use FreeRTOS mutex semaphores as locks.
 * - lock_t is int, but we store an xSemaphoreHandle there.
 * - Locks are no-ops until the FreeRTOS scheduler is running.<commit_msg>syscall write: Should return number of bytes written<commit_after>// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <sys/reent.h>
#include <stdlib.h>
#include "esp_attr.h"
#include "rom/libc_stubs.h"
#include "rom/uart.h"
#include "soc/cpu.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"

void abort() {
    do
    {
        __asm__ ("break 0,0");
        *((int*) 0) = 0;
    } while(true);
}

void* _malloc_r(struct _reent *r, size_t size) {
    return pvPortMalloc(size);
}

void _free_r(struct _reent *r, void* ptr) {
    return vPortFree(ptr);
}

void* _realloc_r(struct _reent *r, void* ptr, size_t size) {
	void* new_chunk;
	if (size == 0) {
		if (ptr) {
			vPortFree(ptr);
		}
		return NULL;
	}

	new_chunk = pvPortMalloc(size);
	if (new_chunk && ptr) {
		memcpy(new_chunk, ptr, size);
		vPortFree(ptr);
	}
	// realloc behaviour: don't free original chunk if alloc failed
	return new_chunk;
}

void* _calloc_r(struct _reent *r, size_t count, size_t size) {
    void* result = pvPortMalloc(count * size);
    if (result)
    {
    	memset(result, 0, count * size);
    }
    return result;
}

int _system_r(struct _reent *r, const char *str) {
    abort();
    return 0;
}

int _rename_r(struct _reent *r, const char *src, const char *dst) {
    abort();
    return 0;
}

clock_t _times_r(struct _reent *r, struct tms *ptms) {
    abort();
    return 0;
}

// TODO: read time from RTC
int _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) {
    abort();
    return 0;
}

void _raise_r(struct _reent *r) {
    abort();
}

int _unlink_r(struct _reent *r, const char *path) {
    abort();
    return 0;
}

int _link_r(struct _reent *r, const char* n1, const char* n2) {
    abort();
    return 0;
}

int _stat_r(struct _reent *r, const char * path, struct stat * st) {
    return 0;
}

int _fstat_r(struct _reent *r, int fd, struct stat * st) {
	st->st_mode = S_IFCHR;
    return 0;
}

void* _sbrk_r(struct _reent *r, ptrdiff_t sz) {
    abort();
    return 0;
}

int _getpid_r(struct _reent *r) {
    abort();
    return 0;
}

int _kill_r(struct _reent *r, int pid, int sig) {
    abort();
    return 0;
}

void _exit_r(struct _reent *r, int e) {
    abort();
}

int _close_r(struct _reent *r, int fd) {
    return 0;
}

int _open_r(struct _reent *r, const char * path, int flags, int mode) {
    return 0;
}

ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) {
    const char *data_c = (const char *)data;
    if (fd == STDOUT_FILENO) {
        static _lock_t stdout_lock; /* lazily initialised */
        /* Even though newlib does stream locking on stdout, we need
           a dedicated stdout UART lock...

           This is because each task has its own _reent structure with
           unique FILEs for stdin/stdout/stderr, so these are
           per-thread (lazily initialised by __sinit the first time a
           stdio function is used, see findfp.c:235.

           It seems like overkill to allocate a FILE-per-task and lock
           a thread-local stream, but I see no easy way to fix this
           (pre-__sinit_, tasks have "fake" FILEs ie __sf_fake_stdout
           which aren't fully valid.)
        */
        _lock_acquire_recursive(&stdout_lock);
        for (size_t i = 0; i < size; i++) {
#if CONFIG_NEWLIB_STDOUT_ADDCR
            if (data_c[i]=='\n') {
                uart_tx_one_char('\r');
            }
#endif
            uart_tx_one_char(data_c[i]);
        }
        _lock_release_recursive(&stdout_lock);
    }
    return size;
}

_off_t _lseek_r(struct _reent *r, int fd, _off_t size, int mode) {
    return 0;
}

// TODO: implement reading from UART
ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size) {
    return 0;
}

/* Notes on our newlib lock implementation:
 *
 * - Use FreeRTOS mutex semaphores as locks.
 * - lock_t is int, but we store an xSemaphoreHandle there.
 * - Locks are no-ops until the FreeRTOS scheduler is running.
{'fraction_non_alphanumeric': 0.1156600748262961, 'fraction_numerical': 0.008230892570817744, 'mean_word_length': 2.903212348769295, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '330120', 'n_tokens_mistral': 3456, 'n_tokens_neox': 3369, 'n_words': 1087}