diff --git a/.gitmodules b/.gitmodules index 19b3794..17f8003 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "lwip/lwip"] path = lwip/lwip - url = https://github.com/SuperHouse/esp-lwip.git + url = https://github.com/ourairquality/lwip.git [submodule "extras/mbedtls/mbedtls"] path = extras/mbedtls/mbedtls url = https://github.com/ARMmbed/mbedtls.git diff --git a/FreeRTOS/License/license.txt b/FreeRTOS/License/license.txt index e48ed80..5d243b8 100644 --- a/FreeRTOS/License/license.txt +++ b/FreeRTOS/License/license.txt @@ -1,65 +1,61 @@ -The FreeRTOS.org source code is licensed by the *modified* GNU General Public -License (GPL), text provided below. A special exception to the GPL is -included to allow you to distribute a combined work that includes FreeRTOS -without being obliged to provide the source code for any proprietary -components. See the licensing section of http://www.FreeRTOS.org for full -details. The exception text is also included at the bottom of this file. +The FreeRTOS open source license covers the FreeRTOS source files, +which are located in the /FreeRTOS/Source directory of the official FreeRTOS +download. It also covers most of the source files in the demo application +projects, which are located in the /FreeRTOS/Demo directory of the official +FreeRTOS download. The demo projects may also include third party software that +is not part of FreeRTOS and is licensed separately to FreeRTOS. Examples of +third party software includes header files provided by chip or tools vendors, +linker scripts, peripheral drivers, etc. All the software in subdirectories of +the /FreeRTOS directory is either open source or distributed with permission, +and is free for use. For the avoidance of doubt, refer to the comments at the +top of each source file. -The FreeRTOS download also includes demo application source code, some of -which is provided by third parties AND IS LICENSED SEPARATELY FROM FREERTOS. +---------------------------------------------------------------------------- -For the avoidance of any doubt refer to the comment included at the top -of each source and header file for license and copyright information. +NOTE: The modification to the GPL is included to allow you to distribute a +combined work that includes FreeRTOS without being obliged to provide the source +code for proprietary components. -This is a list of files for which Real Time Engineers Ltd are not the -copyright owner and are NOT COVERED BY THE GPL. +---------------------------------------------------------------------------- + +Applying to FreeRTOS V8.2.3 up to the latest version, the FreeRTOS GPL Exception +Text follows: + +Any FreeRTOS *source code*, whether modified or in it's original release form, +or whether in whole or in part, can only be distributed by you under the terms +of the GNU General Public License plus this exception. An independent module is +a module which is not derived from or based on FreeRTOS. + +Clause 1: + +Linking FreeRTOS with other modules is making a combined work based on FreeRTOS. +Thus, the terms and conditions of the GNU General Public License V2 cover the +whole combination. + +As a special exception, the copyright holders of FreeRTOS give you permission to +link FreeRTOS with independent modules to produce a statically linked +executable, regardless of the license terms of these independent modules, and to +copy and distribute the resulting executable under terms of your choice, +provided that you also meet, for each linked independent module, the terms and +conditions of the license of that module. An independent module is a module +which is not derived from or based on FreeRTOS. + +Clause 2: + +FreeRTOS may not be used for any competitive or comparative purpose, including +the publication of any form of run time or compile time metric, without the +express permission of Real Time Engineers Ltd. (this is the norm within the +industry and is intended to ensure information accuracy). -1) Various header files provided by silicon manufacturers and tool vendors - that define processor specific memory addresses and utility macros. - Permission has been granted by the various copyright holders for these - files to be included in the FreeRTOS download. Users must ensure license - conditions are adhered to for any use other than compilation of the - FreeRTOS demo applications. - -2) The uIP TCP/IP stack the copyright of which is held by Adam Dunkels. - Users must ensure the open source license conditions stated at the top - of each uIP source file is understood and adhered to. - -3) The lwIP TCP/IP stack the copyright of which is held by the Swedish - Institute of Computer Science. Users must ensure the open source license - conditions stated at the top of each lwIP source file is understood and - adhered to. - -4) Various peripheral driver source files and binaries provided by silicon - manufacturers and tool vendors. Permission has been granted by the - various copyright holders for these files to be included in the FreeRTOS - download. Users must ensure license conditions are adhered to for any - use other than compilation of the FreeRTOS demo applications. - -5) The files contained within FreeRTOS\Demo\WizNET_DEMO_TERN_186\tern_code, - which are slightly modified versions of code provided by and copyright to - Tern Inc. - -Errors and omissions should be reported to Richard Barry, contact details for -whom can be obtained from http://www.FreeRTOS.org. - - - - - -The GPL license text follows. - -A special exception to the GPL is included to allow you to distribute a -combined work that includes FreeRTOS without being obliged to provide -the source code for any proprietary components. See the licensing section -of http://www.FreeRTOS.org for full details. The exception text is also -included at the bottom of this file. -------------------------------------------------------------------- +The standard GPL V2 text: + + GNU GENERAL PUBLIC LICENSE Version 2, June 1991 @@ -401,40 +397,3 @@ consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ----------------------------------------------------------------------------- - -The FreeRTOS GPL Exception Text: - -Any FreeRTOS source code, whether modified or in it's original release form, -or whether in whole or in part, can only be distributed by you under the terms -of the GNU General Public License plus this exception. An independent module is -a module which is not derived from or based on FreeRTOS. - -Clause 1: - -Linking FreeRTOS statically or dynamically with other modules is making a -combined work based on FreeRTOS. Thus, the terms and conditions of the GNU -General Public License cover the whole combination. - -As a special exception, the copyright holder of FreeRTOS gives you permission -to link FreeRTOS with independent modules that communicate with FreeRTOS -solely through the FreeRTOS API interface, regardless of the license terms of -these independent modules, and to copy and distribute the resulting combined -work under terms of your choice, provided that - - + Every copy of the combined work is accompanied by a written statement that - details to the recipient the version of FreeRTOS used and an offer by yourself - to provide the FreeRTOS source code (including any modifications you may have - made) should the recipient request it. - - + The combined work is not itself an RTOS, scheduler, kernel or related product. - - + The independent modules add significant and primary functionality to FreeRTOS - and do not merely extend the existing functionality already present in FreeRTOS. - -Clause 2: - -FreeRTOS may not be used for any competitive or comparative purpose, including the -publication of any form of run time or compile time metric, without the express -permission of Real Time Engineers Ltd. (this is the norm within the industry and -is intended to ensure information accuracy). diff --git a/FreeRTOS/Source/croutine.c b/FreeRTOS/Source/croutine.c index 993e09b..d3b0eff 100644 --- a/FreeRTOS/Source/croutine.c +++ b/FreeRTOS/Source/croutine.c @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/event_groups.c b/FreeRTOS/Source/event_groups.c index b8df5fd..4434bdf 100644 --- a/FreeRTOS/Source/event_groups.c +++ b/FreeRTOS/Source/event_groups.c @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -139,6 +139,16 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, co /* A StaticEventGroup_t object must be provided. */ configASSERT( pxEventGroupBuffer ); + #if( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + variable of type StaticEventGroup_t equals the size of the real + event group structure. */ + volatile size_t xSize = sizeof( StaticEventGroup_t ); + configASSERT( xSize == sizeof( EventGroup_t ) ); + } + #endif /* configASSERT_DEFINED */ + /* The user has provided a statically allocated event group - use it. */ pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */ @@ -602,7 +612,7 @@ BaseType_t xMatchFound = pdFALSE; eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows that is was unblocked due to its required bits matching, rather than because it timed out. */ - ( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); + vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); } /* Move onto the next list item. Note pxListItem->pxNext is not @@ -633,9 +643,9 @@ const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) { /* Unblock the task, returning 0 as the event list is being deleted - and cannot therefore have any bits set. */ - configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); - ( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); + and cannot therefore have any bits set. */ + configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); + vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); } #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 63a08b3..94ea1f8 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -126,6 +126,10 @@ extern "C" { #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. #endif +#if configMAX_PRIORITIES < 1 + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + #ifndef configUSE_PREEMPTION #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif @@ -142,10 +146,6 @@ extern "C" { #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif -#ifndef configMAX_PRIORITIES - #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. -#endif - #ifndef configUSE_CO_ROUTINES #define configUSE_CO_ROUTINES 0 #endif @@ -408,6 +408,14 @@ extern "C" { #define configCHECK_FOR_STACK_OVERFLOW 0 #endif +#ifndef configRECORD_STACK_HIGH_ADDRESS + #define configRECORD_STACK_HIGH_ADDRESS 0 +#endif + +#ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H + #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0 +#endif + /* The following event macros are embedded in the kernel API calls. */ #ifndef traceMOVED_TASK_TO_READY_STATE @@ -708,6 +716,10 @@ extern "C" { #define configUSE_TICKLESS_IDLE 0 #endif +#ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING + #define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x ) +#endif + #ifndef configPRE_SLEEP_PROCESSING #define configPRE_SLEEP_PROCESSING( x ) #endif @@ -724,6 +736,10 @@ extern "C" { #define portTASK_USES_FLOATING_POINT() #endif +#ifndef portTASK_CALLS_SECURE_FUNCTIONS + #define portTASK_CALLS_SECURE_FUNCTIONS() +#endif + #ifndef configUSE_TIME_SLICING #define configUSE_TIME_SLICING 1 #endif @@ -782,6 +798,12 @@ extern "C" { #define configSUPPORT_DYNAMIC_ALLOCATION 1 #endif +#ifndef configSTACK_DEPTH_TYPE + /* Defaults to uint16_t for backward compatibility, but can be overridden + in FreeRTOSConfig.h if uint16_t is too restrictive. */ + #define configSTACK_DEPTH_TYPE uint16_t +#endif + /* Sanity check the configuration. */ #if( configUSE_TICKLESS_IDLE != 0 ) #if( INCLUDE_vTaskSuspend != 1 ) @@ -797,6 +819,10 @@ extern "C" { #error configUSE_MUTEXES must be set to 1 to use recursive mutexes #endif +#ifndef configINITIAL_TICK_COUNT + #define configINITIAL_TICK_COUNT 0 +#endif + #if( portTICK_TYPE_IS_ATOMIC == 0 ) /* Either variables of tick type cannot be read atomically, or portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when @@ -917,7 +943,7 @@ typedef struct xSTATIC_TCB UBaseType_t uxDummy5; void *pxDummy6; uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; - #if ( portSTACK_GROWTH > 0 ) + #if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) ) void *pxDummy8; #endif #if ( portCRITICAL_NESTING_IN_TCB == 1 ) @@ -945,10 +971,14 @@ typedef struct xSTATIC_TCB uint32_t ulDummy18; uint8_t ucDummy19; #endif - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + #if( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) ) uint8_t uxDummy20; #endif + #if( INCLUDE_xTaskAbortDelay == 1 ) + uint8_t ucDummy21; + #endif + } StaticTask_t; /* diff --git a/FreeRTOS/Source/include/FreeRTOSConfig.h b/FreeRTOS/Source/include/FreeRTOSConfig.h index 7df92bf..2d87844 100644 --- a/FreeRTOS/Source/include/FreeRTOSConfig.h +++ b/FreeRTOS/Source/include/FreeRTOSConfig.h @@ -1,15 +1,38 @@ -/* Default esp-open-sdk FreeRTOSConfig file. +/* + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. + All rights reserved - You can override settings in here by creating your own - FreeRTOSConfig.h file in your program directory. + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - You could just copy this file there and edit it, but it's - recommended you instead define whatever you want to override and - then use #include_next to pick up these defaults. + This file is part of the FreeRTOS distribution. - The "blink" example in "examples/blink" provides an example of how - to do this. + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + + For esp-open-rtos, you can override settings in here by creating your own + FreeRTOSConfig.h file in your program directory. You could just copy this + file there and edit it, but it's recommended you instead define whatever you + want to override and then use #include_next to pick up + these defaults. The "blink" example in "examples/blink" provides an example + of how to do this. + + 1 tab == 4 spaces! */ + #ifndef __DEFAULT_FREERTOS_CONFIG_H #define __DEFAULT_FREERTOS_CONFIG_H @@ -20,7 +43,7 @@ * application requirements. * * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. * * See http://www.freertos.org/a00110.html. *----------------------------------------------------------*/ @@ -47,7 +70,7 @@ #define configTICK_RATE_HZ ( ( TickType_t ) 100 ) #endif #ifndef configMAX_PRIORITIES -#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 15 ) +#define configMAX_PRIORITIES ( 15 ) #endif #ifndef configMINIMAL_STACK_SIZE #define configMINIMAL_STACK_SIZE ( ( unsigned short )256 ) @@ -108,6 +131,10 @@ #define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) #endif +#ifndef configUSE_NEWLIB_REENTRANT +#define configUSE_NEWLIB_REENTRANT 1 +#endif + /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ #ifndef INCLUDE_vTaskPrioritySet @@ -144,5 +171,10 @@ to exclude the API function. */ #define configENABLE_BACKWARD_COMPATIBILITY 0 #endif +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +void vAssertCalled(const char * pcFile, unsigned long ulLine); +#define configASSERT(x) if((x) == 0) vAssertCalled(__FILE__, __LINE__); + #endif /* __DEFAULT_FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Source/include/StackMacros.h b/FreeRTOS/Source/include/StackMacros.h index 13c6b82..a3f9335 100644 --- a/FreeRTOS/Source/include/StackMacros.h +++ b/FreeRTOS/Source/include/StackMacros.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/include/croutine.h b/FreeRTOS/Source/include/croutine.h index 4f003a0..f6390de 100644 --- a/FreeRTOS/Source/include/croutine.h +++ b/FreeRTOS/Source/include/croutine.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/include/deprecated_definitions.h b/FreeRTOS/Source/include/deprecated_definitions.h index 4ea816c..de7aef7 100644 --- a/FreeRTOS/Source/include/deprecated_definitions.h +++ b/FreeRTOS/Source/include/deprecated_definitions.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/include/event_groups.h b/FreeRTOS/Source/include/event_groups.h index 7331c91..81b66ca 100644 --- a/FreeRTOS/Source/include/event_groups.h +++ b/FreeRTOS/Source/include/event_groups.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/include/list.h b/FreeRTOS/Source/include/list.h index a080d27..e0f5c27 100644 --- a/FreeRTOS/Source/include/list.h +++ b/FreeRTOS/Source/include/list.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -205,7 +205,7 @@ typedef struct xMINI_LIST_ITEM MiniListItem_t; typedef struct xLIST { listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ - configLIST_VOLATILE UBaseType_t uxNumberOfItems; + volatile UBaseType_t uxNumberOfItems; ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ diff --git a/FreeRTOS/Source/include/mpu_prototypes.h b/FreeRTOS/Source/include/mpu_prototypes.h index 8f7500b..fcc9180 100644 --- a/FreeRTOS/Source/include/mpu_prototypes.h +++ b/FreeRTOS/Source/include/mpu_prototypes.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -83,6 +83,7 @@ BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask ); TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer ); BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); +BaseType_t MPU_xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ); void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions ); void MPU_vTaskDelete( TaskHandle_t xTaskToDelete ); void MPU_vTaskDelay( const TickType_t xTicksToDelay ); @@ -124,7 +125,9 @@ BaseType_t MPU_xTaskGetSchedulerState( void ); /* MPU versions of queue.h API function. */ BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ); -BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ); +BaseType_t MPU_xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ); +BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ); +BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ); UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue ); UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue ); void MPU_vQueueDelete( QueueHandle_t xQueue ); diff --git a/FreeRTOS/Source/include/mpu_wrappers.h b/FreeRTOS/Source/include/mpu_wrappers.h index 78f5a9a..76315e0 100644 --- a/FreeRTOS/Source/include/mpu_wrappers.h +++ b/FreeRTOS/Source/include/mpu_wrappers.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -130,7 +130,9 @@ only for ports that are using the MPU. */ /* Map standard queue.h API functions to the MPU equivalents. */ #define xQueueGenericSend MPU_xQueueGenericSend - #define xQueueGenericReceive MPU_xQueueGenericReceive + #define xQueueReceive MPU_xQueueReceive + #define xQueuePeek MPU_xQueuePeek + #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable #define vQueueDelete MPU_vQueueDelete @@ -177,8 +179,11 @@ only for ports that are using the MPU. */ #define xEventGroupSync MPU_xEventGroupSync #define vEventGroupDelete MPU_vEventGroupDelete - /* Remove the privileged function macro. */ + /* Remove the privileged function macro, but keep the PRIVILEGED_DATA + macro so applications can place data in privileged access sections + (useful when using statically allocated objects). */ #define PRIVILEGED_FUNCTION + #define PRIVILEGED_DATA __attribute__((section("privileged_data"))) #else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ diff --git a/FreeRTOS/Source/include/portable.h b/FreeRTOS/Source/include/portable.h index b9f8be3..5e8303a 100644 --- a/FreeRTOS/Source/include/portable.h +++ b/FreeRTOS/Source/include/portable.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/include/projdefs.h b/FreeRTOS/Source/include/projdefs.h index 0b63fd8..a08f658 100644 --- a/FreeRTOS/Source/include/projdefs.h +++ b/FreeRTOS/Source/include/projdefs.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. diff --git a/FreeRTOS/Source/include/queue.h b/FreeRTOS/Source/include/queue.h index 30be360..bbba834 100644 --- a/FreeRTOS/Source/include/queue.h +++ b/FreeRTOS/Source/include/queue.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -696,12 +696,10 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ *
  BaseType_t xQueuePeek(
 							 QueueHandle_t xQueue,
-							 void *pvBuffer,
+							 void * const pvBuffer,
 							 TickType_t xTicksToWait
 						 );
* - * This is a macro that calls the xQueueGenericReceive() function. - * * Receive an item from a queue without removing the item from the queue. * The item is received by copy so a buffer of adequate size must be * provided. The number of bytes copied into the buffer was defined when @@ -782,10 +780,10 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQ // ... Rest of task code. } - * \defgroup xQueueReceive xQueueReceive + * \defgroup xQueuePeek xQueuePeek * \ingroup QueueManagement */ -#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) +BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * queue. h @@ -829,8 +827,6 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV TickType_t xTicksToWait ); * - * This is a macro that calls the xQueueGenericReceive() function. - * * Receive an item from a queue. The item is received by copy so a buffer of * adequate size must be provided. The number of bytes copied into the buffer * was defined when the queue was created. @@ -911,106 +907,7 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) PRIV * \defgroup xQueueReceive xQueueReceive * \ingroup QueueManagement */ -#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) - - -/** - * queue. h - *
- BaseType_t xQueueGenericReceive(
-									   QueueHandle_t	xQueue,
-									   void	*pvBuffer,
-									   TickType_t	xTicksToWait
-									   BaseType_t	xJustPeek
-									);
- * - * It is preferred that the macro xQueueReceive() be used rather than calling - * this function directly. - * - * Receive an item from a queue. The item is received by copy so a buffer of - * adequate size must be provided. The number of bytes copied into the buffer - * was defined when the queue was created. - * - * This function must not be used in an interrupt service routine. See - * xQueueReceiveFromISR for an alternative that can. - * - * @param xQueue The handle to the queue from which the item is to be - * received. - * - * @param pvBuffer Pointer to the buffer into which the received item will - * be copied. - * - * @param xTicksToWait The maximum amount of time the task should block - * waiting for an item to receive should the queue be empty at the time - * of the call. The time is defined in tick periods so the constant - * portTICK_PERIOD_MS should be used to convert to real time if this is required. - * xQueueGenericReceive() will return immediately if the queue is empty and - * xTicksToWait is 0. - * - * @param xJustPeek When set to true, the item received from the queue is not - * actually removed from the queue - meaning a subsequent call to - * xQueueReceive() will return the same item. When set to false, the item - * being received from the queue is also removed from the queue. - * - * @return pdTRUE if an item was successfully received from the queue, - * otherwise pdFALSE. - * - * Example usage: -
- struct AMessage
- {
-	char ucMessageID;
-	char ucData[ 20 ];
- } xMessage;
-
- QueueHandle_t xQueue;
-
- // Task to create a queue and post a value.
- void vATask( void *pvParameters )
- {
- struct AMessage *pxMessage;
-
-	// Create a queue capable of containing 10 pointers to AMessage structures.
-	// These should be passed by pointer as they contain a lot of data.
-	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
-	if( xQueue == 0 )
-	{
-		// Failed to create the queue.
-	}
-
-	// ...
-
-	// Send a pointer to a struct AMessage object.  Don't block if the
-	// queue is already full.
-	pxMessage = & xMessage;
-	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
-
-	// ... Rest of task code.
- }
-
- // Task to receive from the queue.
- void vADifferentTask( void *pvParameters )
- {
- struct AMessage *pxRxedMessage;
-
-	if( xQueue != 0 )
-	{
-		// Receive a message on the created queue.  Block for 10 ticks if a
-		// message is not immediately available.
-		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
-		{
-			// pcRxedMessage now points to the struct AMessage variable posted
-			// by vATask.
-		}
-	}
-
-	// ... Rest of task code.
- }
- 
- * \defgroup xQueueReceive xQueueReceive - * \ingroup QueueManagement - */ -BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek ) PRIVILEGED_FUNCTION; +BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; /** * queue. h @@ -1560,7 +1457,9 @@ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION; +BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; +void* xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; /* * For internal use only. Use xSemaphoreTakeMutexRecursive() or diff --git a/FreeRTOS/Source/include/semphr.h b/FreeRTOS/Source/include/semphr.h index a674b02..fb76636 100644 --- a/FreeRTOS/Source/include/semphr.h +++ b/FreeRTOS/Source/include/semphr.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -328,7 +328,7 @@ typedef QueueHandle_t SemaphoreHandle_t; * \defgroup xSemaphoreTake xSemaphoreTake * \ingroup Semaphores */ -#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) ) /** * semphr. h @@ -392,23 +392,23 @@ typedef QueueHandle_t SemaphoreHandle_t; // ... // For some reason due to the nature of the code further calls to - // xSemaphoreTakeRecursive() are made on the same mutex. In real - // code these would not be just sequential calls as this would make - // no sense. Instead the calls are likely to be buried inside - // a more complex call structure. + // xSemaphoreTakeRecursive() are made on the same mutex. In real + // code these would not be just sequential calls as this would make + // no sense. Instead the calls are likely to be buried inside + // a more complex call structure. xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); // The mutex has now been 'taken' three times, so will not be - // available to another task until it has also been given back - // three times. Again it is unlikely that real code would have - // these calls sequentially, but instead buried in a more complex - // call structure. This is just for illustrative purposes. + // available to another task until it has also been given back + // three times. Again it is unlikely that real code would have + // these calls sequentially, but instead buried in a more complex + // call structure. This is just for illustrative purposes. + xSemaphoreGiveRecursive( xMutex ); + xSemaphoreGiveRecursive( xMutex ); xSemaphoreGiveRecursive( xMutex ); - xSemaphoreGiveRecursive( xMutex ); - xSemaphoreGiveRecursive( xMutex ); - // Now the mutex can be taken by other tasks. + // Now the mutex can be taken by other tasks. } else { @@ -1154,6 +1154,17 @@ typedef QueueHandle_t SemaphoreHandle_t; */ #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) +/** + * semphr.h + *
TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex );
+ * + * If xMutex is indeed a mutex type semaphore, return the current mutex holder. + * If xMutex is not a mutex type semaphore, or the mutex is available (not held + * by a task), return NULL. + * + */ +#define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) ) + /** * semphr.h *
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h index d0643c0..c326ead 100644 --- a/FreeRTOS/Source/include/task.h +++ b/FreeRTOS/Source/include/task.h @@ -1,5 +1,5 @@ /* - FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd. All rights reserved VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. @@ -160,6 +160,9 @@ typedef struct xTASK_PARAMETERS UBaseType_t uxPriority; StackType_t *puxStackBuffer; MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; + #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + StaticTask_t * const pxTaskBuffer; + #endif } TaskParameters_t; /* Used with the uxTaskGetSystemState() function to return the state of each task @@ -269,7 +272,7 @@ is used in assert() statements. */ BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, - uint16_t usStackDepth, + configSTACK_DEPTH_TYPE usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pvCreatedTask @@ -358,11 +361,11 @@ is used in assert() statements. */ */ #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, - const char * const pcName, - const uint16_t usStackDepth, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + const configSTACK_DEPTH_TYPE usStackDepth, void * const pvParameters, UBaseType_t uxPriority, - TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION; #endif /** @@ -474,12 +477,12 @@ is used in assert() statements. */ */ #if( configSUPPORT_STATIC_ALLOCATION == 1 ) TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, - const char * const pcName, + const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, - StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION; #endif /* configSUPPORT_STATIC_ALLOCATION */ /** @@ -487,6 +490,8 @@ is used in assert() statements. */ *
  BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
* + * Only available when configSUPPORT_DYNAMIC_ALLOCATION is set to 1. + * * xTaskCreateRestricted() should only be used in systems that include an MPU * implementation. * @@ -494,6 +499,9 @@ is used in assert() statements. */ * The function parameters define the memory regions and associated access * permissions allocated to the task. * + * See xTaskCreateRestrictedStatic() for a version that does not use any + * dynamic memory allocation. + * * @param pxTaskDefinition Pointer to a structure that contains a member * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API * documentation) plus an optional stack buffer and the memory region @@ -553,6 +561,94 @@ TaskHandle_t xHandle; BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; #endif +/** + * task. h + *
+ BaseType_t xTaskCreateRestrictedStatic( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * + * Only available when configSUPPORT_STATIC_ALLOCATION is set to 1. + * + * xTaskCreateRestrictedStatic() should only be used in systems that include an + * MPU implementation. + * + * Internally, within the FreeRTOS implementation, tasks use two blocks of + * memory. The first block is used to hold the task's data structures. The + * second block is used by the task as its stack. If a task is created using + * xTaskCreateRestricted() then the stack is provided by the application writer, + * and the memory used to hold the task's data structure is automatically + * dynamically allocated inside the xTaskCreateRestricted() function. If a task + * is created using xTaskCreateRestrictedStatic() then the application writer + * must provide the memory used to hold the task's data structures too. + * xTaskCreateRestrictedStatic() therefore allows a memory protected task to be + * created without using any dynamic memory allocation. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. If configSUPPORT_STATIC_ALLOCATION is set to 1 the structure + * contains an additional member, which is used to point to a variable of type + * StaticTask_t - which is then used to hold the task's data structure. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+// Create an TaskParameters_t structure that defines the task to be created.
+// The StaticTask_t variable is only included in the structure when
+// configSUPPORT_STATIC_ALLOCATION is set to 1.  The PRIVILEGED_DATA macro can
+// be used to force the variable into the RTOS kernel's privileged data area.
+static PRIVILEGED_DATA StaticTask_t xTaskBuffer;
+static const TaskParameters_t xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+
+	&xTaskBuffer; // Holds the task's data structure.
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// and/or timer task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestrictedStatic xTaskCreateRestrictedStatic + * \ingroup Tasks + */ +#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION; +#endif + /** * task. h *
@@ -2141,14 +2237,14 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTi
  * Removes a task from both the specified event list and the list of blocked
  * tasks, and places it on a ready queue.
  *
- * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called
+ * xTaskRemoveFromEventList()/vTaskRemoveFromUnorderedEventList() will be called
  * if either an event occurs to unblock a task, or the block timeout period
  * expires.
  *
  * xTaskRemoveFromEventList() is used when the event list is in task priority
  * order.  It removes the list item from the head of the event list as that will
  * have the highest priority owning task of all the tasks on the event list.
- * xTaskRemoveFromUnorderedEventList() is used when the event list is not
+ * vTaskRemoveFromUnorderedEventList() is used when the event list is not
  * ordered and the event list items hold something other than the owning tasks
  * priority.  In this case the event list item value is updated to the value
  * passed in the xItemValue parameter.
@@ -2157,7 +2253,7 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, TickType_t xTi
  * making the call, otherwise pdFALSE.
  */
 BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) PRIVILEGED_FUNCTION;
-BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION;
+void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue ) PRIVILEGED_FUNCTION;
 
 /*
  * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS ONLY
@@ -2207,7 +2303,7 @@ BaseType_t xTaskGetSchedulerState( void ) PRIVILEGED_FUNCTION;
  * Raises the priority of the mutex holder to that of the calling task should
  * the mutex holder have a priority less than the calling task.
  */
-void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
+BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
 
 /*
  * Set the priority of a task back to its proper priority in the case that it
@@ -2215,6 +2311,16 @@ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTIO
  */
 BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
 
+/*
+ * If a higher priority task attempting to obtain a mutex caused a lower
+ * priority task to inherit the higher priority task's priority - but the higher
+ * priority task then timed out without obtaining the mutex, then the lower
+ * priority task will disinherit the priority again - but only down as far as
+ * the highest priority task that is still waiting for the mutex (if there were
+ * more than one task waiting for the mutex).
+ */
+void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask ) PRIVILEGED_FUNCTION;
+
 /*
  * Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
  */
@@ -2258,6 +2364,13 @@ eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
  */
 void *pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION;
 
+/*
+ * For internal use only.  Same as vTaskSetTimeOutState(), but without a critial
+ * section.
+ */
+void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/FreeRTOS/Source/include/timers.h b/FreeRTOS/Source/include/timers.h
index 798c955..449e49c 100644
--- a/FreeRTOS/Source/include/timers.h
+++ b/FreeRTOS/Source/include/timers.h
@@ -1,5 +1,5 @@
 /*
-    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
     All rights reserved
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -75,10 +75,10 @@
 	#error "include FreeRTOS.h must appear in source files before include timers.h"
 #endif
 
-/*lint -e537 This headers are only multiply included if the application code
+/*lint -save -e537 This headers are only multiply included if the application code
 happens to also be including task.h. */
 #include "task.h"
-/*lint +e537 */
+/*lint -restore */
 
 #ifdef __cplusplus
 extern "C" {
@@ -266,11 +266,11 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
  * @endverbatim
  */
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-	TimerHandle_t xTimerCreate(	const char * const pcTimerName,
+	TimerHandle_t xTimerCreate(	const char * const pcTimerName,			/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 								const TickType_t xTimerPeriodInTicks,
 								const UBaseType_t uxAutoReload,
 								void * const pvTimerID,
-								TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+								TimerCallbackFunction_t pxCallbackFunction ) PRIVILEGED_FUNCTION;
 #endif
 
 /**
@@ -396,12 +396,12 @@ typedef void (*PendedFunction_t)( void *, uint32_t );
  * @endverbatim
  */
 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
-	TimerHandle_t xTimerCreateStatic(	const char * const pcTimerName,
+	TimerHandle_t xTimerCreateStatic(	const char * const pcTimerName,			/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 										const TickType_t xTimerPeriodInTicks,
 										const UBaseType_t uxAutoReload,
 										void * const pvTimerID,
 										TimerCallbackFunction_t pxCallbackFunction,
-										StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+										StaticTimer_t *pxTimerBuffer ) PRIVILEGED_FUNCTION;
 #endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
diff --git a/FreeRTOS/Source/list.c b/FreeRTOS/Source/list.c
index 5e207c1..f890e87 100644
--- a/FreeRTOS/Source/list.c
+++ b/FreeRTOS/Source/list.c
@@ -1,5 +1,5 @@
 /*
-    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
     All rights reserved
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
diff --git a/FreeRTOS/Source/portable/esp8266/port.c b/FreeRTOS/Source/portable/esp8266/port.c
index 87d846f..d6b2a89 100644
--- a/FreeRTOS/Source/portable/esp8266/port.c
+++ b/FreeRTOS/Source/portable/esp8266/port.c
@@ -1,5 +1,5 @@
 /*
-    FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
 
@@ -73,10 +73,12 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "FreeRTOS.h"
 #include "task.h"
+#include "queue.h"
 #include "xtensa_rtos.h"
 
 unsigned cpu_sr;
@@ -91,6 +93,13 @@ char level1_int_disabled;
 */
 void *xPortSupervisorStackPointer;
 
+void vAssertCalled(const char * pcFile, unsigned long ulLine)
+{
+    printf("rtos assert %s %lu\n", pcFile, ulLine);
+    abort();
+    //for (;;);
+}
+
 /*
  * Stack initialization
  */
@@ -100,7 +109,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, TaskFunctio
     portSTACK_TYPE *sp, *tp;
 
     /* Create interrupt stack frame aligned to 16 byte boundary */
-    sp = (portSTACK_TYPE*) (((uint32_t)(pxTopOfStack+1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
+    sp = (portSTACK_TYPE*) (((uint32_t)(pxTopOfStack + 1) - XT_CP_SIZE - XT_STK_FRMSZ) & ~0xf);
 
     /* Clear the entire frame (do not use memset() because we don't depend on C library) */
     for (tp = sp; tp <= pxTopOfStack; ++tp)
@@ -121,30 +130,29 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, TaskFunctio
 static int pending_soft_sv;
 static int pending_maclayer_sv;
 
-/* PendSV is called in place of vPortYield() to request a supervisor
-   call.
-
-   The portYIELD macro calls pendSV if it's a software request.
-
-   The libpp and libudhcp libraries also call this function, assuming
-   always with arg==2 (but maybe sometimes with arg==1?)
-
-   In the original esp_iot_rtos_sdk implementation, arg was a char. Using an
-   enum is ABI-compatible, though.
-*/
+/*
+ * The portYIELD macro calls PendSV with SVC_Software to set a pending interrupt
+ * service callback that allows a task switch, and this occur when interrupts
+ * are enabled which might be after exiting the critical region below.
+ *
+ * The wdev NMI calls this function from pp_post() with SVC_MACLayer to set a
+ * pending interrupt service callback which flushs the queue of messages that
+ * the NMI stashes away. This interrupt will be triggered after the return from
+ * the NMI and when interrupts are enabled. The NMI can not touch the FreeRTOS
+ * queues itself. The NMI must not touch the interrupt masks so that path must
+ * not call vPortEnterCritical and vPortExitCritical.
+ */
 void IRAM PendSV(enum SVC_ReqType req)
 {
-	vPortEnterCritical();
-
-	if(req == SVC_Software)
-	{
-		pending_soft_sv = 1;
-	}
-	else if(req == SVC_MACLayer)
-		pending_maclayer_sv= 1;
-
-	WSR(BIT(INUM_SOFT), interrupt);
-	vPortExitCritical();
+    if (req == SVC_Software) {
+        vPortEnterCritical();
+        pending_soft_sv = 1;
+        WSR(BIT(INUM_SOFT), interrupt);
+        vPortExitCritical();
+    } else if (req == SVC_MACLayer) {
+        pending_maclayer_sv= 1;
+        WSR(BIT(INUM_SOFT), interrupt);
+    }
 }
 
 /* This MAC layer ISR handler is defined in libpp.a, and is called
@@ -153,31 +161,24 @@ void IRAM PendSV(enum SVC_ReqType req)
  */
 extern portBASE_TYPE sdk_MacIsrSigPostDefHdl(void);
 
-void IRAM SV_ISR(void)
+void IRAM SV_ISR(void *arg)
 {
-	portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE ;
-	if(pending_maclayer_sv)
-	{
-		xHigherPriorityTaskWoken = sdk_MacIsrSigPostDefHdl();
-		pending_maclayer_sv = 0;
-	}
-	if( xHigherPriorityTaskWoken || pending_soft_sv)
-	{
-	    sdk__xt_timer_int1();
-	    pending_soft_sv = 0;
-	}
+    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE ;
+    if (pending_maclayer_sv) {
+        xHigherPriorityTaskWoken = sdk_MacIsrSigPostDefHdl();
+        pending_maclayer_sv = 0;
+    }
+    if (xHigherPriorityTaskWoken || pending_soft_sv) {
+        sdk__xt_timer_int1();
+        pending_soft_sv = 0;
+    }
 }
 
 void xPortSysTickHandle (void)
 {
-	//CloseNMI();
-	{
-		if(xTaskIncrementTick() !=pdFALSE )
-		{
-			vTaskSwitchContext();
-		}
-	}
-	//OpenNMI();
+    if (xTaskIncrementTick() != pdFALSE) {
+        vTaskSwitchContext();
+    }
 }
 
 /*
@@ -185,11 +186,11 @@ void xPortSysTickHandle (void)
  */
 portBASE_TYPE xPortStartScheduler( void )
 {
-    _xt_isr_attach(INUM_SOFT, SV_ISR);
+    _xt_isr_attach(INUM_SOFT, SV_ISR, NULL);
     _xt_isr_unmask(BIT(INUM_SOFT));
 
     /* Initialize system tick timer interrupt and schedule the first tick. */
-    _xt_isr_attach(INUM_TICK, sdk__xt_timer_int);
+    _xt_isr_attach(INUM_TICK, sdk__xt_timer_int, NULL);
     _xt_isr_unmask(BIT(INUM_TICK));
     sdk__xt_tick_timer_init();
 
@@ -221,8 +222,10 @@ size_t xPortGetFreeHeapSize( void )
     uint32_t brk_val = (uint32_t) sbrk(0);
 
     intptr_t sp = (intptr_t)xPortSupervisorStackPointer;
-    if(sp == 0) /* scheduler not started */
+    if (sp == 0) {
+        /* scheduler not started */
         SP(sp);
+    }
     return sp - brk_val + mi.fordblks;
 }
 
@@ -233,8 +236,6 @@ void vPortEndScheduler( void )
 
 /*-----------------------------------------------------------*/
 
-/* Each task maintains its own interrupt status in the critical nesting
-variable. */
 static unsigned portBASE_TYPE uxCriticalNesting = 0;
 
 /* These nested vPortEnter/ExitCritical macros are called by SDK
@@ -243,26 +244,42 @@ static unsigned portBASE_TYPE uxCriticalNesting = 0;
  * It may be possible to replace the global nesting count variable
  * with a save/restore of interrupt level, although it's difficult as
  * the functions have no return value.
+ *
+ * These should not be called from the NMI in regular operation and
+ * the NMI must not touch the interrupt mask, but that might occur in
+ * exceptional paths such as aborts and debug code.
  */
-void IRAM vPortEnterCritical( void )
-{
+void IRAM vPortEnterCritical(void) {
     portDISABLE_INTERRUPTS();
     uxCriticalNesting++;
 }
+
 /*-----------------------------------------------------------*/
 
-void IRAM vPortExitCritical( void )
-{
+void IRAM vPortExitCritical(void) {
     uxCriticalNesting--;
-    if( uxCriticalNesting == 0 )
-	portENABLE_INTERRUPTS();
+    if (uxCriticalNesting == 0)
+        portENABLE_INTERRUPTS();
 }
 
-/* Backward compatibility with libmain.a and libpp.a and can remove when these are open. */
-signed portBASE_TYPE xTaskGenericCreate( TaskFunction_t pxTaskCode, const signed char * const pcName, unsigned short usStackDepth, void *pvParameters, unsigned portBASE_TYPE uxPriority, TaskHandle_t *pxCreatedTask, portSTACK_TYPE *puxStackBuffer, const MemoryRegion_t * const xRegions )
-{
-    (void)puxStackBuffer; (void)xRegions;
-    return xTaskCreate( pxTaskCode, (const char * const)pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
+/* Backward compatibility, for the sdk library. */
+
+signed portBASE_TYPE xTaskGenericCreate(TaskFunction_t pxTaskCode,
+                                        const signed char * const pcName,
+                                        unsigned short usStackDepth,
+                                        void *pvParameters,
+                                        unsigned portBASE_TYPE uxPriority,
+                                        TaskHandle_t *pxCreatedTask,
+                                        portSTACK_TYPE *puxStackBuffer,
+                                        const MemoryRegion_t * const xRegions) {
+    (void)puxStackBuffer;
+    (void)xRegions;
+    return xTaskCreate(pxTaskCode, (const char * const)pcName, usStackDepth,
+                       pvParameters, uxPriority, pxCreatedTask);
 }
 
-
+BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void * const pvBuffer,
+                                TickType_t xTicksToWait, const BaseType_t xJustPeeking) {
+    configASSERT(xJustPeeking == 0);
+    return xQueueReceive(xQueue, pvBuffer, xTicksToWait);
+}
diff --git a/FreeRTOS/Source/portable/esp8266/portmacro.h b/FreeRTOS/Source/portable/esp8266/portmacro.h
index 68d5e57..0b18b47 100644
--- a/FreeRTOS/Source/portable/esp8266/portmacro.h
+++ b/FreeRTOS/Source/portable/esp8266/portmacro.h
@@ -1,65 +1,29 @@
 /*
-    FreeRTOS V7.5.2 - Copyright (C) 2013 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
+    All rights reserved
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
 
-    ***************************************************************************
-     *                                                                       *
-     *    FreeRTOS provides completely free yet professionally developed,    *
-     *    robust, strictly quality controlled, supported, and cross          *
-     *    platform software that has become a de facto standard.             *
-     *                                                                       *
-     *    Help yourself get started quickly and support the FreeRTOS         *
-     *    project by purchasing a FreeRTOS tutorial book, reference          *
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *
-     *                                                                       *
-     *    Thank you!                                                         *
-     *                                                                       *
-    ***************************************************************************
-
     This file is part of the FreeRTOS distribution.
 
     FreeRTOS is free software; you can redistribute it and/or modify it under
     the terms of the GNU General Public License (version 2) as published by the
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
 
-    >>! NOTE: The modification to the GPL is included to allow you to distribute
-    >>! a combined work that includes FreeRTOS without being obliged to provide
-    >>! the source code for proprietary components outside of the FreeRTOS
-    >>! kernel.
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
 
     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-    FOR A PARTICULAR PURPOSE.  Full license text is available from the following
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
     link: http://www.freertos.org/a00114.html
 
     1 tab == 4 spaces!
 
-    ***************************************************************************
-     *                                                                       *
-     *    Having a problem?  Start by reading the FAQ "My application does   *
-     *    not run, what could be wrong?"                                     *
-     *                                                                       *
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *
-     *                                                                       *
-    ***************************************************************************
-
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,
-    license and Real Time Engineers Ltd. contact details.
-
-    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
-    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
-    compatible FAT file system, and our tiny thread aware UDP/IP stack.
-
-    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS
-    licenses offer ticketed support, indemnification and middleware.
-
-    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
-    engineered and independently SIL3 certified version for use in safety and
-    mission critical applications that require provable dependability.
-
-    1 tab == 4 spaces!
 */
 
 
@@ -92,16 +56,15 @@ extern "C" {
 #define portDOUBLE              double
 #define portLONG                long
 #define portSHORT               short
-#define portSTACK_TYPE          unsigned portLONG
+#define portSTACK_TYPE          uint32_t
 #define portBASE_TYPE           long
-#define portPOINTER_SIZE_TYPE   unsigned portLONG
 
 typedef portSTACK_TYPE StackType_t;
 typedef portBASE_TYPE BaseType_t;
 typedef unsigned portBASE_TYPE UBaseType_t;
 
 typedef uint32_t TickType_t;
-#define portMAX_DELAY ( TickType_t ) 0xffffffff
+#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
 
 /* Architecture specifics. */
 #define portSTACK_GROWTH			( -1 )
@@ -156,6 +119,9 @@ extern unsigned cpu_sr;
    prefer to _xt_disable_interrupts & _xt_enable_interrupts and store
    the ps value in a local variable - that approach is recursive-safe
    and generally better.
+
+   The NMI must not touch the interrupt mask and it should not in
+   regular operation, but there is a guard here just in case.
 */
 inline static __attribute__((always_inline)) void portDISABLE_INTERRUPTS(void)
 {
@@ -185,6 +151,10 @@ not necessary for to use this port.  They are defined so the common demo files
 (which build with all the ports) will build. */
 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+
+/* FreeRTOS API functions should not be called from the NMI handler. */
+#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT(sdk_NMIIrqIsOn == 0)
+
 /*-----------------------------------------------------------*/
 
 #ifdef __cplusplus
diff --git a/FreeRTOS/Source/portable/readme.txt b/FreeRTOS/Source/portable/readme.txt
new file mode 100644
index 0000000..b68d2d5
--- /dev/null
+++ b/FreeRTOS/Source/portable/readme.txt
@@ -0,0 +1,20 @@
+Each real time kernel port consists of three files that contain the core kernel
+components and are common to every port, and one or more files that are
+specific to a particular microcontroller and/or compiler.
+
+
++ The FreeRTOS/Source/Portable/MemMang directory contains the five sample
+memory allocators as described on the http://www.FreeRTOS.org WEB site.
+
++ The other directories each contain files specific to a particular
+microcontroller or compiler, where the directory name denotes the compiler
+specific files the directory contains.
+
+
+
+For example, if you are interested in the [compiler] port for the [architecture]
+microcontroller, then the port specific files are contained in
+FreeRTOS/Source/Portable/[compiler]/[architecture] directory.  If this is the
+only port you are interested in then all the other directories can be
+ignored.
+
diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c
index ce623be..d076022 100644
--- a/FreeRTOS/Source/queue.c
+++ b/FreeRTOS/Source/queue.c
@@ -1,5 +1,5 @@
 /*
-    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
     All rights reserved
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -255,6 +255,16 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
 	static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION;
 #endif
 
+#if( configUSE_MUTEXES == 1 )
+	/*
+	 * If a task waiting for a mutex causes the mutex holder to inherit a
+	 * priority, but the waiting task times out, then the holder should
+	 * disinherit the priority - but only down to the highest priority of any
+	 * other tasks that are waiting for the same mutex.  This function returns
+	 * that priority.
+	 */
+	static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
+#endif
 /*-----------------------------------------------------------*/
 
 /*
@@ -374,6 +384,10 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 
 			prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
 		}
+		else
+		{
+			traceQUEUE_CREATE_FAILED( ucQueueType );
+		}
 
 		return pxNewQueue;
 	}
@@ -422,6 +436,10 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 
 			prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );
 		}
+		else
+		{
+			traceQUEUE_CREATE_FAILED( ucQueueType );
+		}
 
 		return pxNewQueue;
 	}
@@ -567,6 +585,32 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
 #endif
 /*-----------------------------------------------------------*/
 
+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
+
+	void* xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )
+	{
+	void *pxReturn;
+
+		configASSERT( xSemaphore );
+
+		/* Mutexes cannot be used in interrupt service routines, so the mutex
+		holder should not change in an ISR, and therefore a critical section is
+		not required here. */
+		if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
+		{
+			pxReturn = ( void * ) ( ( Queue_t * ) xSemaphore )->pxMutexHolder;
+		}
+		else
+		{
+			pxReturn = NULL;
+		}
+
+		return pxReturn;
+	} /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
+
+#endif
+/*-----------------------------------------------------------*/
+
 #if ( configUSE_RECURSIVE_MUTEXES == 1 )
 
 	BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
@@ -643,7 +687,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseT
 		}
 		else
 		{
-			xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE );
+			xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );
 
 			/* pdPASS will only be returned if the mutex was successfully
 			obtained.  The calling task may have entered the Blocked state
@@ -855,7 +899,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 				{
 					/* The queue was full and a block time was specified so
 					configure the timeout structure. */
-					vTaskSetTimeOutState( &xTimeOut );
+					vTaskInternalSetTimeOutState( &xTimeOut );
 					xEntryTimeSet = pdTRUE;
 				}
 				else
@@ -1127,7 +1171,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 			can be assumed there is no mutex holder and no need to determine if
 			priority disinheritance is needed.  Simply increase the count of
 			messages (semaphores) available. */
-			pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1;
+			pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
 
 			/* The event list is not altered if the queue is locked.  This will
 			be done when the queue is unlocked later. */
@@ -1234,21 +1278,27 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 }
 /*-----------------------------------------------------------*/
 
-BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
+BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
 {
 BaseType_t xEntryTimeSet = pdFALSE;
 TimeOut_t xTimeOut;
-int8_t *pcOriginalReadPosition;
 Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 
-	configASSERT( pxQueue );
-	configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
+	/* Check the pointer is not NULL. */
+	configASSERT( ( pxQueue ) );
+
+	/* The buffer into which data is received can only be NULL if the data size
+	is zero (so no data is copied into the buffer. */
+	configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
+
+	/* Cannot block if the scheduler is suspended. */
 	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
 	{
 		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
 	}
 	#endif
 
+
 	/* This function relaxes the coding standard somewhat to allow return
 	statements within the function itself.  This is done in the interest
 	of execution time efficiency. */
@@ -1263,44 +1313,19 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 			must be the highest priority task wanting to access the queue. */
 			if( uxMessagesWaiting > ( UBaseType_t ) 0 )
 			{
-				/* Remember the read position in case the queue is only being
-				peeked. */
-				pcOriginalReadPosition = pxQueue->u.pcReadFrom;
-
+				/* Data available, remove one item. */
 				prvCopyDataFromQueue( pxQueue, pvBuffer );
+				traceQUEUE_RECEIVE( pxQueue );
+				pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
 
-				if( xJustPeeking == pdFALSE )
+				/* There is now space in the queue, were any tasks waiting to
+				post to the queue?  If so, unblock the highest priority waiting
+				task. */
+				if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
 				{
-					traceQUEUE_RECEIVE( pxQueue );
-
-					/* Actually removing data, not just peeking. */
-					pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;
-
-					#if ( configUSE_MUTEXES == 1 )
+					if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
 					{
-						if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
-						{
-							/* Record the information required to implement
-							priority inheritance should it become necessary. */
-							pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
-						}
-						else
-						{
-							mtCOVERAGE_TEST_MARKER();
-						}
-					}
-					#endif /* configUSE_MUTEXES */
-
-					if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
-					{
-						if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
-						{
-							queueYIELD_IF_USING_PREEMPTION();
-						}
-						else
-						{
-							mtCOVERAGE_TEST_MARKER();
-						}
+						queueYIELD_IF_USING_PREEMPTION();
 					}
 					else
 					{
@@ -1309,30 +1334,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 				}
 				else
 				{
-					traceQUEUE_PEEK( pxQueue );
-
-					/* The data is not being removed, so reset the read
-					pointer. */
-					pxQueue->u.pcReadFrom = pcOriginalReadPosition;
-
-					/* The data is being left in the queue, so see if there are
-					any other tasks waiting for the data. */
-					if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
-					{
-						if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
-						{
-							/* The task waiting has a higher priority than this task. */
-							queueYIELD_IF_USING_PREEMPTION();
-						}
-						else
-						{
-							mtCOVERAGE_TEST_MARKER();
-						}
-					}
-					else
-					{
-						mtCOVERAGE_TEST_MARKER();
-					}
+					mtCOVERAGE_TEST_MARKER();
 				}
 
 				taskEXIT_CRITICAL();
@@ -1352,7 +1354,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 				{
 					/* The queue was empty and a block time was specified so
 					configure the timeout structure. */
-					vTaskSetTimeOutState( &xTimeOut );
+					vTaskInternalSetTimeOutState( &xTimeOut );
 					xEntryTimeSet = pdTRUE;
 				}
 				else
@@ -1373,6 +1375,182 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 		/* Update the timeout state to see if it has expired yet. */
 		if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
 		{
+			/* The timeout has not expired.  If the queue is still empty place
+			the task on the list of tasks waiting to receive from the queue. */
+			if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+			{
+				traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+				vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+				prvUnlockQueue( pxQueue );
+				if( xTaskResumeAll() == pdFALSE )
+				{
+					portYIELD_WITHIN_API();
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				/* The queue contains data again.  Loop back to try and read the
+				data. */
+				prvUnlockQueue( pxQueue );
+				( void ) xTaskResumeAll();
+			}
+		}
+		else
+		{
+			/* Timed out.  If there is no data in the queue exit, otherwise loop
+			back and attempt to read the data. */
+			prvUnlockQueue( pxQueue );
+			( void ) xTaskResumeAll();
+
+			if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+			{
+				traceQUEUE_RECEIVE_FAILED( pxQueue );
+				return errQUEUE_EMPTY;
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait )
+{
+BaseType_t xEntryTimeSet = pdFALSE;
+TimeOut_t xTimeOut;
+Queue_t * const pxQueue = ( Queue_t * ) xQueue;
+
+#if( configUSE_MUTEXES == 1 )
+	BaseType_t xInheritanceOccurred = pdFALSE;
+#endif
+
+	/* Check the queue pointer is not NULL. */
+	configASSERT( ( pxQueue ) );
+
+	/* Check this really is a semaphore, in which case the item size will be
+	0. */
+	configASSERT( pxQueue->uxItemSize == 0 );
+
+	/* Cannot block if the scheduler is suspended. */
+	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+	{
+		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+	}
+	#endif
+
+
+	/* This function relaxes the coding standard somewhat to allow return
+	statements within the function itself.  This is done in the interest
+	of execution time efficiency. */
+
+	for( ;; )
+	{
+		taskENTER_CRITICAL();
+		{
+			/* Semaphores are queues with an item size of 0, and where the
+			number of messages in the queue is the semaphore's count value. */
+			const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
+
+			/* Is there data in the queue now?  To be running the calling task
+			must be the highest priority task wanting to access the queue. */
+			if( uxSemaphoreCount > ( UBaseType_t ) 0 )
+			{
+				traceQUEUE_RECEIVE( pxQueue );
+
+				/* Semaphores are queues with a data size of zero and where the
+				messages waiting is the semaphore's count.  Reduce the count. */
+				pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1;
+
+				#if ( configUSE_MUTEXES == 1 )
+				{
+					if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
+					{
+						/* Record the information required to implement
+						priority inheritance should it become necessary. */
+						pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+				}
+				#endif /* configUSE_MUTEXES */
+
+				/* Check to see if other tasks are blocked waiting to give the
+				semaphore, and if so, unblock the highest priority such task. */
+				if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
+				{
+					if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
+					{
+						queueYIELD_IF_USING_PREEMPTION();
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+
+				taskEXIT_CRITICAL();
+				return pdPASS;
+			}
+			else
+			{
+				if( xTicksToWait == ( TickType_t ) 0 )
+				{
+					/* For inheritance to have occurred there must have been an
+					initial timeout, and an adjusted timeout cannot become 0, as
+					if it were 0 the function would have exited. */
+					#if( configUSE_MUTEXES == 1 )
+					{
+						configASSERT( xInheritanceOccurred == pdFALSE );
+					}
+					#endif /* configUSE_MUTEXES */
+
+					/* The semaphore count was 0 and no block time is specified
+					(or the block time has expired) so exit now. */
+					taskEXIT_CRITICAL();
+					traceQUEUE_RECEIVE_FAILED( pxQueue );
+					return errQUEUE_EMPTY;
+				}
+				else if( xEntryTimeSet == pdFALSE )
+				{
+					/* The semaphore count was 0 and a block time was specified
+					so configure the timeout structure ready to block. */
+					vTaskInternalSetTimeOutState( &xTimeOut );
+					xEntryTimeSet = pdTRUE;
+				}
+				else
+				{
+					/* Entry time was already set. */
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+		}
+		taskEXIT_CRITICAL();
+
+		/* Interrupts and other tasks can give to and take from the semaphore
+		now the critical section has been exited. */
+
+		vTaskSuspendAll();
+		prvLockQueue( pxQueue );
+
+		/* Update the timeout state to see if it has expired yet. */
+		if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+		{
+			/* A block time is specified and not expired.  If the semaphore
+			count is 0 then enter the Blocked state to wait for a semaphore to
+			become available.  As semaphores are implemented with queues the
+			queue being empty is equivalent to the semaphore count being 0. */
 			if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
 			{
 				traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
@@ -1383,7 +1561,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 					{
 						taskENTER_CRITICAL();
 						{
-							vTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
+							xInheritanceOccurred = xTaskPriorityInherit( ( void * ) pxQueue->pxMutexHolder );
 						}
 						taskEXIT_CRITICAL();
 					}
@@ -1407,13 +1585,193 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 			}
 			else
 			{
-				/* Try again. */
+				/* There was no timeout and the semaphore count was not 0, so
+				attempt to take the semaphore again. */
 				prvUnlockQueue( pxQueue );
 				( void ) xTaskResumeAll();
 			}
 		}
 		else
 		{
+			/* Timed out. */
+			prvUnlockQueue( pxQueue );
+			( void ) xTaskResumeAll();
+
+			/* If the semaphore count is 0 exit now as the timeout has
+			expired.  Otherwise return to attempt to take the semaphore that is
+			known to be available.  As semaphores are implemented by queues the
+			queue being empty is equivalent to the semaphore count being 0. */
+			if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+			{
+				#if ( configUSE_MUTEXES == 1 )
+				{
+					/* xInheritanceOccurred could only have be set if
+					pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
+					test the mutex type again to check it is actually a mutex. */
+					if( xInheritanceOccurred != pdFALSE )
+					{
+						taskENTER_CRITICAL();
+						{
+							UBaseType_t uxHighestWaitingPriority;
+
+							/* This task blocking on the mutex caused another
+							task to inherit this task's priority.  Now this task
+							has timed out the priority should be disinherited
+							again, but only as low as the next highest priority
+							task that is waiting for the same mutex. */
+							uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
+							vTaskPriorityDisinheritAfterTimeout( ( void * ) pxQueue->pxMutexHolder, uxHighestWaitingPriority );
+						}
+						taskEXIT_CRITICAL();
+					}
+				}
+				#endif /* configUSE_MUTEXES */
+
+				traceQUEUE_RECEIVE_FAILED( pxQueue );
+				return errQUEUE_EMPTY;
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+	}
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait )
+{
+BaseType_t xEntryTimeSet = pdFALSE;
+TimeOut_t xTimeOut;
+int8_t *pcOriginalReadPosition;
+Queue_t * const pxQueue = ( Queue_t * ) xQueue;
+
+	/* Check the pointer is not NULL. */
+	configASSERT( ( pxQueue ) );
+
+	/* The buffer into which data is received can only be NULL if the data size
+	is zero (so no data is copied into the buffer. */
+	configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) );
+
+	/* Cannot block if the scheduler is suspended. */
+	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
+	{
+		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
+	}
+	#endif
+
+
+	/* This function relaxes the coding standard somewhat to allow return
+	statements within the function itself.  This is done in the interest
+	of execution time efficiency. */
+
+	for( ;; )
+	{
+		taskENTER_CRITICAL();
+		{
+			const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
+
+			/* Is there data in the queue now?  To be running the calling task
+			must be the highest priority task wanting to access the queue. */
+			if( uxMessagesWaiting > ( UBaseType_t ) 0 )
+			{
+				/* Remember the read position so it can be reset after the data
+				is read from the queue as this function is only peeking the
+				data, not removing it. */
+				pcOriginalReadPosition = pxQueue->u.pcReadFrom;
+
+				prvCopyDataFromQueue( pxQueue, pvBuffer );
+				traceQUEUE_PEEK( pxQueue );
+
+				/* The data is not being removed, so reset the read pointer. */
+				pxQueue->u.pcReadFrom = pcOriginalReadPosition;
+
+				/* The data is being left in the queue, so see if there are
+				any other tasks waiting for the data. */
+				if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
+				{
+					if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
+					{
+						/* The task waiting has a higher priority than this task. */
+						queueYIELD_IF_USING_PREEMPTION();
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+
+				taskEXIT_CRITICAL();
+				return pdPASS;
+			}
+			else
+			{
+				if( xTicksToWait == ( TickType_t ) 0 )
+				{
+					/* The queue was empty and no block time is specified (or
+					the block time has expired) so leave now. */
+					taskEXIT_CRITICAL();
+					traceQUEUE_RECEIVE_FAILED( pxQueue );
+					return errQUEUE_EMPTY;
+				}
+				else if( xEntryTimeSet == pdFALSE )
+				{
+					/* The queue was empty and a block time was specified so
+					configure the timeout structure ready to enter the blocked
+					state. */
+					vTaskInternalSetTimeOutState( &xTimeOut );
+					xEntryTimeSet = pdTRUE;
+				}
+				else
+				{
+					/* Entry time was already set. */
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+		}
+		taskEXIT_CRITICAL();
+
+		/* Interrupts and other tasks can send to and receive from the queue
+		now the critical section has been exited. */
+
+		vTaskSuspendAll();
+		prvLockQueue( pxQueue );
+
+		/* Update the timeout state to see if it has expired yet. */
+		if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
+		{
+			/* Timeout has not expired yet, check to see if there is data in the
+			queue now, and if not enter the Blocked state to wait for data. */
+			if( prvIsQueueEmpty( pxQueue ) != pdFALSE )
+			{
+				traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue );
+				vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+				prvUnlockQueue( pxQueue );
+				if( xTaskResumeAll() == pdFALSE )
+				{
+					portYIELD_WITHIN_API();
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				/* There is data in the queue now, so don't enter the blocked
+				state, instead return to try and obtain the data. */
+				prvUnlockQueue( pxQueue );
+				( void ) xTaskResumeAll();
+			}
+		}
+		else
+		{
+			/* The timeout has expired.  If there is still no data in the queue
+			exit, otherwise go back and try to read the data again. */
 			prvUnlockQueue( pxQueue );
 			( void ) xTaskResumeAll();
 
@@ -1468,7 +1826,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 			traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
 
 			prvCopyDataFromQueue( pxQueue, pvBuffer );
-			pxQueue->uxMessagesWaiting = uxMessagesWaiting - 1;
+			pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
 
 			/* If the queue is locked the event list will not be modified.
 			Instead update the lock count so the task that unlocks the queue
@@ -1694,6 +2052,33 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
 #endif /* configUSE_TRACE_FACILITY */
 /*-----------------------------------------------------------*/
 
+#if( configUSE_MUTEXES == 1 )
+
+	static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )
+	{
+	UBaseType_t uxHighestPriorityOfWaitingTasks;
+
+		/* If a task waiting for a mutex causes the mutex holder to inherit a
+		priority, but the waiting task times out, then the holder should
+		disinherit the priority - but only down to the highest priority of any
+		other tasks that are waiting for the same mutex.  For this purpose,
+		return the priority of the highest priority task that is waiting for the
+		mutex. */
+		if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0 )
+		{
+			uxHighestPriorityOfWaitingTasks = configMAX_PRIORITIES - listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) );
+		}
+		else
+		{
+			uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;
+		}
+
+		return uxHighestPriorityOfWaitingTasks;
+	}
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
 static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition )
 {
 BaseType_t xReturn = pdFALSE;
@@ -1767,7 +2152,7 @@ UBaseType_t uxMessagesWaiting;
 		}
 	}
 
-	pxQueue->uxMessagesWaiting = uxMessagesWaiting + 1;
+	pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
 
 	return xReturn;
 }
@@ -2316,7 +2701,7 @@ BaseType_t xReturn;
 		}
 
 		return pcReturn;
-	}
+	} /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */
 
 #endif /* configQUEUE_REGISTRY_SIZE */
 /*-----------------------------------------------------------*/
@@ -2395,7 +2780,7 @@ BaseType_t xReturn;
 	{
 	QueueSetHandle_t pxQueue;
 
-		pxQueue = xQueueGenericCreate( uxEventQueueLength, sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
+		pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET );
 
 		return pxQueue;
 	}
@@ -2478,7 +2863,7 @@ BaseType_t xReturn;
 	{
 	QueueSetMemberHandle_t xReturn = NULL;
 
-		( void ) xQueueGenericReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait, pdFALSE ); /*lint !e961 Casting from one typedef to another is not redundant. */
+		( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */
 		return xReturn;
 	}
 
diff --git a/FreeRTOS/Source/readme.txt b/FreeRTOS/Source/readme.txt
index 58480c5..b68d2d5 100644
--- a/FreeRTOS/Source/readme.txt
+++ b/FreeRTOS/Source/readme.txt
@@ -1,17 +1,20 @@
 Each real time kernel port consists of three files that contain the core kernel
-components and are common to every port, and one or more files that are 
-specific to a particular microcontroller and or compiler.
+components and are common to every port, and one or more files that are
+specific to a particular microcontroller and/or compiler.
 
-+ The FreeRTOS/Source directory contains the three files that are common to 
-every port - list.c, queue.c and tasks.c.  The kernel is contained within these 
-three files.  croutine.c implements the optional co-routine functionality - which
-is normally only used on very memory limited systems.
 
-+ The FreeRTOS/Source/Portable directory contains the files that are specific to 
-a particular microcontroller and or compiler.
++ The FreeRTOS/Source/Portable/MemMang directory contains the five sample
+memory allocators as described on the http://www.FreeRTOS.org WEB site.
 
-+ The FreeRTOS/Source/include directory contains the real time kernel header 
-files.
++ The other directories each contain files specific to a particular
+microcontroller or compiler, where the directory name denotes the compiler
+specific files the directory contains.
+
+
+
+For example, if you are interested in the [compiler] port for the [architecture]
+microcontroller, then the port specific files are contained in
+FreeRTOS/Source/Portable/[compiler]/[architecture] directory.  If this is the
+only port you are interested in then all the other directories can be
+ignored.
 
-See the readme file in the FreeRTOS/Source/Portable directory for more 
-information.
\ No newline at end of file
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c
index 6c261a6..dd6a69d 100644
--- a/FreeRTOS/Source/tasks.c
+++ b/FreeRTOS/Source/tasks.c
@@ -1,5 +1,5 @@
 /*
-    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
     All rights reserved
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -131,12 +131,23 @@ made to free the RAM that was allocated statically.
 tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a
 task to be created using either statically or dynamically allocated RAM.  Note
 that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with
-a statically allocated stack and a dynamically allocated TCB. */
-#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE ( ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) || ( portUSING_MPU_WRAPPERS == 1 ) )
+a statically allocated stack and a dynamically allocated TCB.
+!!!NOTE!!! If the definition of tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is
+changed then the definition of StaticTask_t must also be updated. */
+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE	( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 #define tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB 		( ( uint8_t ) 0 )
 #define tskSTATICALLY_ALLOCATED_STACK_ONLY 			( ( uint8_t ) 1 )
 #define tskSTATICALLY_ALLOCATED_STACK_AND_TCB		( ( uint8_t ) 2 )
 
+/* If any of the following are set then task stacks are filled with a known
+value so the high water mark can be determined.  If none of the following are
+set then don't fill the stack so there is no unnecessary dependency on memset. */
+#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+	#define tskSET_NEW_STACKS_TO_KNOWN_VALUE	1
+#else
+	#define tskSET_NEW_STACKS_TO_KNOWN_VALUE	0
+#endif
+
 /*
  * Macros used by vListTask to indicate which state a task is in.
  */
@@ -153,6 +164,12 @@ a statically allocated stack and a dynamically allocated TCB. */
 	#define static
 #endif
 
+/* The name allocated to the Idle task.  This can be overridden by defining
+configIDLE_TASK_NAME in FreeRTOSConfig.h. */
+#ifndef configIDLE_TASK_NAME
+	#define configIDLE_TASK_NAME "IDLE"
+#endif
+
 #if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
 
 	/* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is
@@ -304,8 +321,8 @@ typedef struct tskTaskControlBlock
 	StackType_t			*pxStack;			/*< Points to the start of the stack. */
 	char				pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 
-	#if ( portSTACK_GROWTH > 0 )
-		StackType_t		*pxEndOfStack;		/*< Points to the end of the stack on architectures where the stack grows up from low memory. */
+	#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
+		StackType_t		*pxEndOfStack;		/*< Points to the highest valid address for the stack. */
 	#endif
 
 	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
@@ -327,7 +344,7 @@ typedef struct tskTaskControlBlock
 	#endif
 
 	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
-		void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
+		void			*pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
 	#endif
 
 	#if( configGENERATE_RUN_TIME_STATS == 1 )
@@ -352,7 +369,7 @@ typedef struct tskTaskControlBlock
 
 	/* See the comments above the definition of
 	tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
-	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
 		uint8_t	ucStaticallyAllocated; 		/*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
 	#endif
 
@@ -366,8 +383,8 @@ typedef struct tskTaskControlBlock
 below to enable the use of older kernel aware debuggers. */
 typedef tskTCB TCB_t;
 
-/*lint -e956 A manual analysis and inspection has been used to determine which
-static variables must be declared volatile. */
+/*lint -save -e956 A manual analysis and inspection has been used to determine
+which static variables must be declared volatile. */
 
 PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;
 
@@ -394,7 +411,7 @@ PRIVILEGED_DATA static List_t xPendingReadyList;						/*< Tasks that have been r
 
 /* Other file private variables. --------------------------------*/
 PRIVILEGED_DATA static volatile UBaseType_t uxCurrentNumberOfTasks 	= ( UBaseType_t ) 0U;
-PRIVILEGED_DATA static volatile TickType_t xTickCount 				= ( TickType_t ) 0U;
+PRIVILEGED_DATA static volatile TickType_t xTickCount 				= ( TickType_t ) configINITIAL_TICK_COUNT;
 PRIVILEGED_DATA static volatile UBaseType_t uxTopReadyPriority 		= tskIDLE_PRIORITY;
 PRIVILEGED_DATA static volatile BaseType_t xSchedulerRunning 		= pdFALSE;
 PRIVILEGED_DATA static volatile UBaseType_t uxPendedTicks 			= ( UBaseType_t ) 0U;
@@ -421,21 +438,27 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended	= ( UBaseType_t
 
 #endif
 
-/*lint +e956 */
+/*lint -restore */
 
 /*-----------------------------------------------------------*/
 
 /* Callback function prototypes. --------------------------*/
 #if(  configCHECK_FOR_STACK_OVERFLOW > 0 )
+
 	extern void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName );
+
 #endif
 
 #if( configUSE_TICK_HOOK > 0 )
+
 	extern void vApplicationTickHook( void );
+
 #endif
 
 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
+
 	extern void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
+
 #endif
 
 /* File private functions. --------------------------------*/
@@ -446,7 +469,9 @@ PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended	= ( UBaseType_t
  * is in any other state.
  */
 #if ( INCLUDE_vTaskSuspend == 1 )
+
 	static BaseType_t prvTaskIsTaskSuspended( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
+
 #endif /* INCLUDE_vTaskSuspend */
 
 /*
@@ -565,13 +590,13 @@ static void prvResetNextTaskUnblockTime( void );
  * dynamically to fill in the structure's members.
  */
 static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,
-									const char * const pcName,
+									const char * const pcName, 		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 									const uint32_t ulStackDepth,
 									void * const pvParameters,
 									UBaseType_t uxPriority,
 									TaskHandle_t * const pxCreatedTask,
 									TCB_t *pxNewTCB,
-									const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+									const MemoryRegion_t * const xRegions ) PRIVILEGED_FUNCTION;
 
 /*
  * Called after a new task has been created and initialised to place the task
@@ -579,17 +604,28 @@ static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,
  */
 static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 
+/*
+ * freertos_tasks_c_additions_init() should only be called if the user definable
+ * macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is the only macro
+ * called by the function.
+ */
+#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+
+	static void freertos_tasks_c_additions_init( void ) PRIVILEGED_FUNCTION;
+
+#endif
+
 /*-----------------------------------------------------------*/
 
 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
 
 	TaskHandle_t xTaskCreateStatic(	TaskFunction_t pxTaskCode,
-									const char * const pcName,
+									const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 									const uint32_t ulStackDepth,
 									void * const pvParameters,
 									UBaseType_t uxPriority,
 									StackType_t * const puxStackBuffer,
-									StaticTask_t * const pxTaskBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+									StaticTask_t * const pxTaskBuffer )
 	{
 	TCB_t *pxNewTCB;
 	TaskHandle_t xReturn;
@@ -597,6 +633,17 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 		configASSERT( puxStackBuffer != NULL );
 		configASSERT( pxTaskBuffer != NULL );
 
+		#if( configASSERT_DEFINED == 1 )
+		{
+			/* Sanity check that the size of the structure used to declare a
+			variable of type StaticTask_t equals the size of the real task
+			structure. */
+			volatile size_t xSize = sizeof( StaticTask_t );
+			configASSERT( xSize == sizeof( TCB_t ) );
+		}
+		#endif /* configASSERT_DEFINED */
+
+
 		if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
 		{
 			/* The memory used for the task's TCB and stack are passed into this
@@ -604,7 +651,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 			pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
 			pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
 
-			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
 			{
 				/* Tasks can be created statically or dynamically, so note this
 				task was created statically in case the task is later deleted. */
@@ -626,7 +673,53 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 #endif /* SUPPORT_STATIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
-#if( portUSING_MPU_WRAPPERS == 1 )
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+
+	BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
+	{
+	TCB_t *pxNewTCB;
+	BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+
+		configASSERT( pxTaskDefinition->puxStackBuffer != NULL );
+		configASSERT( pxTaskDefinition->pxTaskBuffer != NULL );
+
+		if( ( pxTaskDefinition->puxStackBuffer != NULL ) && ( pxTaskDefinition->pxTaskBuffer != NULL ) )
+		{
+			/* Allocate space for the TCB.  Where the memory comes from depends
+			on the implementation of the port malloc function and whether or
+			not static allocation is being used. */
+			pxNewTCB = ( TCB_t * ) pxTaskDefinition->pxTaskBuffer;
+
+			/* Store the stack location in the TCB. */
+			pxNewTCB->pxStack = pxTaskDefinition->puxStackBuffer;
+
+			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+			{
+				/* Tasks can be created statically or dynamically, so note this
+				task was created statically in case the task is later deleted. */
+				pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+			}
+			#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
+
+			prvInitialiseNewTask(	pxTaskDefinition->pvTaskCode,
+									pxTaskDefinition->pcName,
+									( uint32_t ) pxTaskDefinition->usStackDepth,
+									pxTaskDefinition->pvParameters,
+									pxTaskDefinition->uxPriority,
+									pxCreatedTask, pxNewTCB,
+									pxTaskDefinition->xRegions );
+
+			prvAddNewTaskToReadyList( pxNewTCB );
+			xReturn = pdPASS;
+		}
+
+		return xReturn;
+	}
+
+#endif /* ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+/*-----------------------------------------------------------*/
+
+#if( ( portUSING_MPU_WRAPPERS == 1 ) && ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) )
 
 	BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask )
 	{
@@ -674,11 +767,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
 
 	BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,
-							const char * const pcName,
-							const uint16_t usStackDepth,
+							const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+							const configSTACK_DEPTH_TYPE usStackDepth,
 							void * const pvParameters,
 							UBaseType_t uxPriority,
-							TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+							TaskHandle_t * const pxCreatedTask )
 	{
 	TCB_t *pxNewTCB;
 	BaseType_t xReturn;
@@ -741,7 +834,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 
 		if( pxNewTCB != NULL )
 		{
-			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
+			#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
 			{
 				/* Tasks can be created statically or dynamically, so note this
 				task was created dynamically in case it is later deleted. */
@@ -765,13 +858,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 static void prvInitialiseNewTask( 	TaskFunction_t pxTaskCode,
-									const char * const pcName,
+									const char * const pcName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 									const uint32_t ulStackDepth,
 									void * const pvParameters,
 									UBaseType_t uxPriority,
 									TaskHandle_t * const pxCreatedTask,
 									TCB_t *pxNewTCB,
-									const MemoryRegion_t * const xRegions ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+									const MemoryRegion_t * const xRegions )
 {
 StackType_t *pxTopOfStack;
 UBaseType_t x;
@@ -791,12 +884,12 @@ UBaseType_t x;
 	#endif /* portUSING_MPU_WRAPPERS == 1 */
 
 	/* Avoid dependency on memset() if it is not required. */
-	#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
+	#if( tskSET_NEW_STACKS_TO_KNOWN_VALUE == 1 )
 	{
 		/* Fill the stack with a known value to assist debugging. */
 		( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) ulStackDepth * sizeof( StackType_t ) );
 	}
-	#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
+	#endif /* tskSET_NEW_STACKS_TO_KNOWN_VALUE */
 
 	/* Calculate the top of stack address.  This depends on whether the stack
 	grows from high memory to low (as per the 80x86) or vice versa.
@@ -809,6 +902,14 @@ UBaseType_t x;
 
 		/* Check the alignment of the calculated top of stack is correct. */
 		configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
+
+		#if( configRECORD_STACK_HIGH_ADDRESS == 1 )
+		{
+			/* Also record the stack's high address, which may assist
+			debugging. */
+			pxNewTCB->pxEndOfStack = pxTopOfStack;
+		}
+		#endif /* configRECORD_STACK_HIGH_ADDRESS */
 	}
 	#else /* portSTACK_GROWTH */
 	{
@@ -936,7 +1037,7 @@ UBaseType_t x;
 	/* Initialize the TCB stack to look as if the task was already running,
 	but had been interrupted by the scheduler.  The return address is set
 	to the start of the task function. Once the stack has been initialised
-	the	top of stack variable is updated. */
+	the top of stack variable is updated. */
 	#if( portUSING_MPU_WRAPPERS == 1 )
 	{
 		pxNewTCB->pxTopOfStack = pxPortInitialiseStack( pxTopOfStack, pxTaskCode, pvParameters, xRunPrivileged );
@@ -1515,14 +1616,14 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
 				}
 
 				/* If the task is in the blocked or suspended list we need do
-				nothing more than change it's priority variable. However, if
+				nothing more than change its priority variable. However, if
 				the task is in a ready list it needs to be removed and placed
 				in the list appropriate to its new priority. */
 				if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
 				{
-					/* The task is currently in its ready list - remove before adding
-					it to it's new ready list.  As we are in a critical section we
-					can do this even if the scheduler is suspended. */
+					/* The task is currently in its ready list - remove before
+					adding it to it's new ready list.  As we are in a critical
+					section we can do this even if the scheduler is suspended. */
 					if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 					{
 						/* It is known that the task is in its ready list so
@@ -1597,6 +1698,17 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
 			}
 
 			vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
+
+			#if( configUSE_TASK_NOTIFICATIONS == 1 )
+			{
+				if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION )
+				{
+					/* The task was blocked to wait for a notification, but is
+					now suspended, so no notification was received. */
+					pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION;
+				}
+			}
+			#endif
 		}
 		taskEXIT_CRITICAL();
 
@@ -1672,7 +1784,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
 			{
 				/* Is it in the suspended list because it is in the	Suspended
 				state, or because is is blocked with no timeout? */
-				if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE )
+				if( listIS_CONTAINED_WITHIN( NULL, &( pxTCB->xEventListItem ) ) != pdFALSE ) /*lint !e961.  The cast is only redundant when NULL is used. */
 				{
 					xReturn = pdTRUE;
 				}
@@ -1716,12 +1828,12 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB )
 				{
 					traceTASK_RESUME( pxTCB );
 
-					/* As we are in a critical section we can access the ready
-					lists even if the scheduler is suspended. */
+					/* The ready list can be accessed even if the scheduler is
+					suspended because this is inside a critical section. */
 					( void ) uxListRemove(  &( pxTCB->xStateListItem ) );
 					prvAddTaskToReadyList( pxTCB );
 
-					/* We may have just resumed a higher priority task. */
+					/* A higher priority task may have just been resumed. */
 					if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
 					{
 						/* This yield may not cause the task just resumed to run,
@@ -1838,9 +1950,9 @@ BaseType_t xReturn;
 		address of the RAM then create the idle task. */
 		vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
 		xIdleTaskHandle = xTaskCreateStatic(	prvIdleTask,
-												"IDLE",
+												configIDLE_TASK_NAME,
 												ulIdleTaskStackSize,
-												( void * ) NULL,
+												( void * ) NULL, /*lint !e961.  The cast is not redundant for all compilers. */
 												( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
 												pxIdleTaskStackBuffer,
 												pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
@@ -1858,7 +1970,8 @@ BaseType_t xReturn;
 	{
 		/* The Idle task is being created using dynamically allocated RAM. */
 		xReturn = xTaskCreate(	prvIdleTask,
-								"IDLE", configMINIMAL_STACK_SIZE,
+								configIDLE_TASK_NAME,
+								configMINIMAL_STACK_SIZE,
 								( void * ) NULL,
 								( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
 								&xIdleTaskHandle ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
@@ -1880,6 +1993,15 @@ BaseType_t xReturn;
 
 	if( xReturn == pdPASS )
 	{
+		/* freertos_tasks_c_additions_init() should only be called if the user
+		definable macro FREERTOS_TASKS_C_ADDITIONS_INIT() is defined, as that is
+		the only macro called by the function. */
+		#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+		{
+			freertos_tasks_c_additions_init();
+		}
+		#endif
+
 		/* Interrupts are turned off here, to ensure a tick does not occur
 		before or during the call to xPortStartScheduler().  The stacks of
 		the created tasks contain a status word with interrupts switched on
@@ -1901,7 +2023,10 @@ BaseType_t xReturn;
 
 		/* If configGENERATE_RUN_TIME_STATS is defined then the following
 		macro must be defined to configure the timer/counter used to generate
-		the run time counter time base. */
+		the run time counter time base.   NOTE:  If configGENERATE_RUN_TIME_STATS
+		is set to 0 and the following line fails to build then ensure you do not
+		have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your
+		FreeRTOSConfig.h file. */
 		portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
 
 		/* Setting up the timer tick is hardware specific and thus in the
@@ -2427,7 +2552,7 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
 	BaseType_t xTaskAbortDelay( TaskHandle_t xTask )
 	{
 	TCB_t *pxTCB = ( TCB_t * ) xTask;
-	BaseType_t xReturn = pdFALSE;
+	BaseType_t xReturn;
 
 		configASSERT( pxTCB );
 
@@ -2437,6 +2562,8 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
 			it is actually in the Blocked state. */
 			if( eTaskGetState( xTask ) == eBlocked )
 			{
+				xReturn = pdPASS;
+
 				/* Remove the reference to the task from the blocked list.  An
 				interrupt won't touch the xStateListItem because the
 				scheduler is suspended. */
@@ -2485,10 +2612,10 @@ implementations require configUSE_TICKLESS_IDLE to be set to a value other than
 			}
 			else
 			{
-				mtCOVERAGE_TEST_MARKER();
+				xReturn = pdFAIL;
 			}
 		}
-		xTaskResumeAll();
+		( void ) xTaskResumeAll();
 
 		return xReturn;
 	}
@@ -2510,13 +2637,13 @@ BaseType_t xSwitchRequired = pdFALSE;
 	{
 		/* Minor optimisation.  The tick count cannot change in this
 		block. */
-		const TickType_t xConstTickCount = xTickCount + 1;
+		const TickType_t xConstTickCount = xTickCount + ( TickType_t ) 1;
 
 		/* Increment the RTOS tick, switching the delayed and overflowed
 		delayed lists if it wraps to 0. */
 		xTickCount = xConstTickCount;
 
-		if( xConstTickCount == ( TickType_t ) 0U )
+		if( xConstTickCount == ( TickType_t ) 0U ) /*lint !e774 'if' does not always evaluate to false as it is looking for an overflow. */
 		{
 			taskSWITCH_DELAYED_LISTS();
 		}
@@ -2959,10 +3086,9 @@ BaseType_t xReturn;
 }
 /*-----------------------------------------------------------*/
 
-BaseType_t xTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
+void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, const TickType_t xItemValue )
 {
 TCB_t *pxUnblockedTCB;
-BaseType_t xReturn;
 
 	/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
 	the event flags implementation. */
@@ -2985,28 +3111,30 @@ BaseType_t xReturn;
 
 	if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )
 	{
-		/* Return true if the task removed from the event list has
-		a higher priority than the calling task.  This allows
-		the calling task to know if it should force a context
-		switch now. */
-		xReturn = pdTRUE;
-
-		/* Mark that a yield is pending in case the user is not using the
-		"xHigherPriorityTaskWoken" parameter to an ISR safe FreeRTOS function. */
+		/* The unblocked task has a priority above that of the calling task, so
+		a context switch is required.  This function is called with the
+		scheduler suspended so xYieldPending is set so the context switch
+		occurs immediately that the scheduler is resumed (unsuspended). */
 		xYieldPending = pdTRUE;
 	}
-	else
-	{
-		xReturn = pdFALSE;
-	}
-
-	return xReturn;
 }
 /*-----------------------------------------------------------*/
 
 void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
 {
 	configASSERT( pxTimeOut );
+	taskENTER_CRITICAL();
+	{
+		pxTimeOut->xOverflowCount = xNumOfOverflows;
+		pxTimeOut->xTimeOnEntering = xTickCount;
+	}
+	taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
+void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
+{
+	/* For internal use only as it does not use a critical section. */
 	pxTimeOut->xOverflowCount = xNumOfOverflows;
 	pxTimeOut->xTimeOnEntering = xTickCount;
 }
@@ -3023,6 +3151,7 @@ BaseType_t xReturn;
 	{
 		/* Minor optimisation.  The tick count cannot change in this block. */
 		const TickType_t xConstTickCount = xTickCount;
+		const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
 
 		#if( INCLUDE_xTaskAbortDelay == 1 )
 			if( pxCurrentTCB->ucDelayAborted != pdFALSE )
@@ -3055,11 +3184,11 @@ BaseType_t xReturn;
 			was called. */
 			xReturn = pdTRUE;
 		}
-		else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
+		else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
 		{
 			/* Not a genuine timeout. Adjust parameters for time remaining. */
-			*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );
-			vTaskSetTimeOutState( pxTimeOut );
+			*pxTicksToWait -= xElapsedTime;
+			vTaskInternalSetTimeOutState( pxTimeOut );
 			xReturn = pdFALSE;
 		}
 		else
@@ -3136,6 +3265,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
 	/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
 	SCHEDULER IS STARTED. **/
 
+	/* In case a task that has a secure context deletes itself, in which case
+	the idle task is responsible for deleting the task's secure context, if
+	any. */
+	portTASK_CALLS_SECURE_FUNCTIONS();
+
 	for( ;; )
 	{
 		/* See if any tasks have deleted themselves - if so then the idle task
@@ -3212,6 +3346,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
 					configASSERT( xNextTaskUnblockTime >= xTickCount );
 					xExpectedIdleTime = prvGetExpectedIdleTime();
 
+					/* Define the following macro to set xExpectedIdleTime to 0
+					if the application does not want
+					portSUPPRESS_TICKS_AND_SLEEP() to be called. */
+					configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );
+
 					if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
 					{
 						traceLOW_POWER_IDLE_BEGIN();
@@ -3369,37 +3508,22 @@ static void prvCheckTasksWaitingTermination( void )
 
 	#if ( INCLUDE_vTaskDelete == 1 )
 	{
-		BaseType_t xListIsEmpty;
+		TCB_t *pxTCB;
 
-		/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
-		too often in the idle task. */
+		/* uxDeletedTasksWaitingCleanUp is used to prevent vTaskSuspendAll()
+		being called too often in the idle task. */
 		while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
 		{
-			vTaskSuspendAll();
+			taskENTER_CRITICAL();
 			{
-				xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
+				pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
+				( void ) uxListRemove( &( pxTCB->xStateListItem ) );
+				--uxCurrentNumberOfTasks;
+				--uxDeletedTasksWaitingCleanUp;
 			}
-			( void ) xTaskResumeAll();
+			taskEXIT_CRITICAL();
 
-			if( xListIsEmpty == pdFALSE )
-			{
-				TCB_t *pxTCB;
-
-				taskENTER_CRITICAL();
-				{
-					pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
-					( void ) uxListRemove( &( pxTCB->xStateListItem ) );
-					--uxCurrentNumberOfTasks;
-					--uxDeletedTasksWaitingCleanUp;
-				}
-				taskEXIT_CRITICAL();
-
-				prvDeleteTCB( pxTCB );
-			}
-			else
-			{
-				mtCOVERAGE_TEST_MARKER();
-			}
+			prvDeleteTCB( pxTCB );
 		}
 	}
 	#endif /* INCLUDE_vTaskDelete */
@@ -3421,25 +3545,6 @@ static void prvCheckTasksWaitingTermination( void )
 		pxTaskStatus->pxStackBase = pxTCB->pxStack;
 		pxTaskStatus->xTaskNumber = pxTCB->uxTCBNumber;
 
-		#if ( INCLUDE_vTaskSuspend == 1 )
-		{
-			/* If the task is in the suspended list then there is a chance it is
-			actually just blocked indefinitely - so really it should be reported as
-			being in the Blocked state. */
-			if( pxTaskStatus->eCurrentState == eSuspended )
-			{
-				vTaskSuspendAll();
-				{
-					if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
-					{
-						pxTaskStatus->eCurrentState = eBlocked;
-					}
-				}
-				xTaskResumeAll();
-			}
-		}
-		#endif /* INCLUDE_vTaskSuspend */
-
 		#if ( configUSE_MUTEXES == 1 )
 		{
 			pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
@@ -3460,12 +3565,38 @@ static void prvCheckTasksWaitingTermination( void )
 		}
 		#endif
 
-		/* Obtaining the task state is a little fiddly, so is only done if the value
-		of eState passed into this function is eInvalid - otherwise the state is
-		just set to whatever is passed in. */
+		/* Obtaining the task state is a little fiddly, so is only done if the
+		value of eState passed into this function is eInvalid - otherwise the
+		state is just set to whatever is passed in. */
 		if( eState != eInvalid )
 		{
-			pxTaskStatus->eCurrentState = eState;
+			if( pxTCB == pxCurrentTCB )
+			{
+				pxTaskStatus->eCurrentState = eRunning;
+			}
+			else
+			{
+				pxTaskStatus->eCurrentState = eState;
+
+				#if ( INCLUDE_vTaskSuspend == 1 )
+				{
+					/* If the task is in the suspended list then there is a
+					chance it is actually just blocked indefinitely - so really
+					it should be reported as being in the Blocked state. */
+					if( eState == eSuspended )
+					{
+						vTaskSuspendAll();
+						{
+							if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) != NULL )
+							{
+								pxTaskStatus->eCurrentState = eBlocked;
+							}
+						}
+						( void ) xTaskResumeAll();
+					}
+				}
+				#endif /* INCLUDE_vTaskSuspend */
+			}
 		}
 		else
 		{
@@ -3499,7 +3630,7 @@ static void prvCheckTasksWaitingTermination( void )
 
 	static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t *pxTaskStatusArray, List_t *pxList, eTaskState eState )
 	{
-	volatile TCB_t *pxNextTCB, *pxFirstTCB;
+	configLIST_VOLATILE TCB_t *pxNextTCB, *pxFirstTCB;
 	UBaseType_t uxTask = 0;
 
 		if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
@@ -3600,7 +3731,7 @@ static void prvCheckTasksWaitingTermination( void )
 			vPortFree( pxTCB->pxStack );
 			vPortFree( pxTCB );
 		}
-		#elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE == 1 )
+		#elif( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 Macro has been consolidated for readability reasons. */
 		{
 			/* The task could have been allocated statically or dynamically, so
 			check what was statically allocated before trying to free the
@@ -3622,7 +3753,7 @@ static void prvCheckTasksWaitingTermination( void )
 			{
 				/* Neither the stack nor the TCB were allocated dynamically, so
 				nothing needs to be freed. */
-				configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB	)
+				configASSERT( pxTCB->ucStaticallyAllocated == tskSTATICALLY_ALLOCATED_STACK_AND_TCB	);
 				mtCOVERAGE_TEST_MARKER();
 			}
 		}
@@ -3703,25 +3834,27 @@ TCB_t *pxTCB;
 
 #if ( configUSE_MUTEXES == 1 )
 
-	void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
+	BaseType_t xTaskPriorityInherit( TaskHandle_t const pxMutexHolder )
 	{
-	TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
+	TCB_t * const pxMutexHolderTCB = ( TCB_t * ) pxMutexHolder;
+	BaseType_t xReturn = pdFALSE;
 
 		/* If the mutex was given back by an interrupt while the queue was
-		locked then the mutex holder might now be NULL. */
+		locked then the mutex holder might now be NULL.  _RB_ Is this still
+		needed as interrupts can no longer use mutexes? */
 		if( pxMutexHolder != NULL )
 		{
 			/* If the holder of the mutex has a priority below the priority of
 			the task attempting to obtain the mutex then it will temporarily
 			inherit the priority of the task attempting to obtain the mutex. */
-			if( pxTCB->uxPriority < pxCurrentTCB->uxPriority )
+			if( pxMutexHolderTCB->uxPriority < pxCurrentTCB->uxPriority )
 			{
 				/* Adjust the mutex holder state to account for its new
 				priority.  Only reset the event list item value if the value is
-				not	being used for anything else. */
-				if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
+				not being used for anything else. */
+				if( ( listGET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
 				{
-					listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+					listSET_LIST_ITEM_VALUE( &( pxMutexHolderTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) pxCurrentTCB->uxPriority ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
 				}
 				else
 				{
@@ -3730,11 +3863,11 @@ TCB_t *pxTCB;
 
 				/* If the task being modified is in the ready state it will need
 				to be moved into a new list. */
-				if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
+				if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxMutexHolderTCB->uxPriority ] ), &( pxMutexHolderTCB->xStateListItem ) ) != pdFALSE )
 				{
-					if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+					if( uxListRemove( &( pxMutexHolderTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 					{
-						taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+						taskRESET_READY_PRIORITY( pxMutexHolderTCB->uxPriority );
 					}
 					else
 					{
@@ -3742,26 +3875,45 @@ TCB_t *pxTCB;
 					}
 
 					/* Inherit the priority before being moved into the new list. */
-					pxTCB->uxPriority = pxCurrentTCB->uxPriority;
-					prvAddTaskToReadyList( pxTCB );
+					pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
+					prvAddTaskToReadyList( pxMutexHolderTCB );
 				}
 				else
 				{
 					/* Just inherit the priority. */
-					pxTCB->uxPriority = pxCurrentTCB->uxPriority;
+					pxMutexHolderTCB->uxPriority = pxCurrentTCB->uxPriority;
 				}
 
-				traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB->uxPriority );
+				traceTASK_PRIORITY_INHERIT( pxMutexHolderTCB, pxCurrentTCB->uxPriority );
+
+				/* Inheritance occurred. */
+				xReturn = pdTRUE;
 			}
 			else
 			{
-				mtCOVERAGE_TEST_MARKER();
+				if( pxMutexHolderTCB->uxBasePriority < pxCurrentTCB->uxPriority )
+				{
+					/* The base priority of the mutex holder is lower than the
+					priority of the task attempting to take the mutex, but the
+					current priority of the mutex holder is not lower than the
+					priority of the task attempting to take the mutex.
+					Therefore the mutex holder must have already inherited a
+					priority, but inheritance would have occurred if that had
+					not been the case. */
+					xReturn = pdTRUE;
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
 			}
 		}
 		else
 		{
 			mtCOVERAGE_TEST_MARKER();
 		}
+
+		return xReturn;
 	}
 
 #endif /* configUSE_MUTEXES */
@@ -3781,7 +3933,6 @@ TCB_t *pxTCB;
 			interrupt, and if a mutex is given by the holding task then it must
 			be the running state task. */
 			configASSERT( pxTCB == pxCurrentTCB );
-
 			configASSERT( pxTCB->uxMutexesHeld );
 			( pxTCB->uxMutexesHeld )--;
 
@@ -3795,8 +3946,8 @@ TCB_t *pxTCB;
 					/* A task can only have an inherited priority if it holds
 					the mutex.  If the mutex is held by a task then it cannot be
 					given from an interrupt, and if a mutex is given by the
-					holding	task then it must be the running state task.  Remove
-					the	holding task from the ready	list. */
+					holding task then it must be the running state task.  Remove
+					the holding task from the ready list. */
 					if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
 					{
 						taskRESET_READY_PRIORITY( pxTCB->uxPriority );
@@ -3848,6 +3999,108 @@ TCB_t *pxTCB;
 #endif /* configUSE_MUTEXES */
 /*-----------------------------------------------------------*/
 
+#if ( configUSE_MUTEXES == 1 )
+
+	void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder, UBaseType_t uxHighestPriorityWaitingTask )
+	{
+	TCB_t * const pxTCB = ( TCB_t * ) pxMutexHolder;
+	UBaseType_t uxPriorityUsedOnEntry, uxPriorityToUse;
+	const UBaseType_t uxOnlyOneMutexHeld = ( UBaseType_t ) 1;
+
+		if( pxMutexHolder != NULL )
+		{
+			/* If pxMutexHolder is not NULL then the holder must hold at least
+			one mutex. */
+			configASSERT( pxTCB->uxMutexesHeld );
+
+			/* Determine the priority to which the priority of the task that
+			holds the mutex should be set.  This will be the greater of the
+			holding task's base priority and the priority of the highest
+			priority task that is waiting to obtain the mutex. */
+			if( pxTCB->uxBasePriority < uxHighestPriorityWaitingTask )
+			{
+				uxPriorityToUse = uxHighestPriorityWaitingTask;
+			}
+			else
+			{
+				uxPriorityToUse = pxTCB->uxBasePriority;
+			}
+
+			/* Does the priority need to change? */
+			if( pxTCB->uxPriority != uxPriorityToUse )
+			{
+				/* Only disinherit if no other mutexes are held.  This is a
+				simplification in the priority inheritance implementation.  If
+				the task that holds the mutex is also holding other mutexes then
+				the other mutexes may have caused the priority inheritance. */
+				if( pxTCB->uxMutexesHeld == uxOnlyOneMutexHeld )
+				{
+					/* If a task has timed out because it already holds the
+					mutex it was trying to obtain then it cannot of inherited
+					its own priority. */
+					configASSERT( pxTCB != pxCurrentTCB );
+
+					/* Disinherit the priority, remembering the previous
+					priority to facilitate determining the subject task's
+					state. */
+					traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
+					uxPriorityUsedOnEntry = pxTCB->uxPriority;
+					pxTCB->uxPriority = uxPriorityToUse;
+
+					/* Only reset the event list item value if the value is not
+					being used for anything else. */
+					if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
+					{
+						listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxPriorityToUse ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+
+					/* If the running task is not the task that holds the mutex
+					then the task that holds the mutex could be in either the
+					Ready, Blocked or Suspended states.  Only remove the task
+					from its current state list if it is in the Ready state as
+					the task's priority is going to change and there is one
+					Ready list per priority. */
+					if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
+					{
+						if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
+						{
+							taskRESET_READY_PRIORITY( pxTCB->uxPriority );
+						}
+						else
+						{
+							mtCOVERAGE_TEST_MARKER();
+						}
+
+						prvAddTaskToReadyList( pxTCB );
+					}
+					else
+					{
+						mtCOVERAGE_TEST_MARKER();
+					}
+				}
+				else
+				{
+					mtCOVERAGE_TEST_MARKER();
+				}
+			}
+			else
+			{
+				mtCOVERAGE_TEST_MARKER();
+			}
+		}
+		else
+		{
+			mtCOVERAGE_TEST_MARKER();
+		}
+	}
+
+#endif /* configUSE_MUTEXES */
+/*-----------------------------------------------------------*/
+
 #if ( portCRITICAL_NESTING_IN_TCB == 1 )
 
 	void vTaskEnterCritical( void )
@@ -3937,7 +4190,7 @@ TCB_t *pxTCB;
 #endif /* ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) */
 /*-----------------------------------------------------------*/
 
-#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	void vTaskList( char * pcWriteBuffer )
 	{
@@ -4029,10 +4282,10 @@ TCB_t *pxTCB;
 		}
 	}
 
-#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+#endif /* ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
 /*----------------------------------------------------------*/
 
-#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
+#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 
 	void vTaskGetRunTimeStats( char *pcWriteBuffer )
 	{
@@ -4156,7 +4409,7 @@ TCB_t *pxTCB;
 		}
 	}
 
-#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) ) */
+#endif /* ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
 /*-----------------------------------------------------------*/
 
 TickType_t uxTaskResetEventItemValue( void )
@@ -4240,7 +4493,7 @@ TickType_t uxReturn;
 				}
 				else
 				{
-					pxCurrentTCB->ulNotifiedValue = ulReturn - 1;
+					pxCurrentTCB->ulNotifiedValue = ulReturn - ( uint32_t ) 1;
 				}
 			}
 			else
@@ -4315,7 +4568,7 @@ TickType_t uxReturn;
 			blocked state (because a notification was already pending) or the
 			task unblocked because of a notification.  Otherwise the task
 			unblocked because of a timeout. */
-			if( pxCurrentTCB->ucNotifyState == taskWAITING_NOTIFICATION )
+			if( pxCurrentTCB->ucNotifyState != taskNOTIFICATION_RECEIVED )
 			{
 				/* A notification was not received. */
 				xReturn = pdFALSE;
@@ -4800,8 +5053,24 @@ const TickType_t xConstTickCount = xTickCount;
 	#endif /* INCLUDE_vTaskSuspend */
 }
 
+/* Code below here allows additional code to be inserted into this source file,
+especially where access to file scope functions and data is needed (for example
+when performing module tests). */
 
 #ifdef FREERTOS_MODULE_TEST
 	#include "tasks_test_access_functions.h"
 #endif
 
+
+#if( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 )
+
+	#include "freertos_tasks_c_additions.h"
+
+	static void freertos_tasks_c_additions_init( void )
+	{
+		#ifdef FREERTOS_TASKS_C_ADDITIONS_INIT
+			FREERTOS_TASKS_C_ADDITIONS_INIT();
+		#endif
+	}
+
+#endif
diff --git a/FreeRTOS/Source/timers.c b/FreeRTOS/Source/timers.c
index d4a821a..44d63aa 100644
--- a/FreeRTOS/Source/timers.c
+++ b/FreeRTOS/Source/timers.c
@@ -1,5 +1,5 @@
 /*
-    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.
     All rights reserved
 
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@@ -100,6 +100,12 @@ configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */
 /* Misc definitions. */
 #define tmrNO_DELAY		( TickType_t ) 0U
 
+/* The name assigned to the timer service task.  This can be overridden by
+defining trmTIMER_SERVICE_TASK_NAME in FreeRTOSConfig.h. */
+#ifndef configTIMER_SERVICE_TASK_NAME
+	#define configTIMER_SERVICE_TASK_NAME "Tmr Svc"
+#endif
+
 /* The definition of the timers themselves. */
 typedef struct tmrTimerControl
 {
@@ -158,8 +164,8 @@ typedef struct tmrTimerQueueMessage
 	} u;
 } DaemonTaskMessage_t;
 
-/*lint -e956 A manual analysis and inspection has been used to determine which
-static variables must be declared volatile. */
+/*lint -save -e956 A manual analysis and inspection has been used to determine
+which static variables must be declared volatile. */
 
 /* The list in which active timers are stored.  Timers are referenced in expire
 time order, with the nearest expiry time at the front of the list.  Only the
@@ -173,7 +179,7 @@ PRIVILEGED_DATA static List_t *pxOverflowTimerList;
 PRIVILEGED_DATA static QueueHandle_t xTimerQueue = NULL;
 PRIVILEGED_DATA static TaskHandle_t xTimerTaskHandle = NULL;
 
-/*lint +e956 */
+/*lint -restore */
 
 /*-----------------------------------------------------------*/
 
@@ -248,12 +254,12 @@ static void prvProcessTimerOrBlockTask( const TickType_t xNextExpireTime, BaseTy
  * Called after a Timer_t structure has been allocated either statically or
  * dynamically to fill in the structure's members.
  */
-static void prvInitialiseNewTimer(	const char * const pcTimerName,
+static void prvInitialiseNewTimer(	const char * const pcTimerName,			/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 									const TickType_t xTimerPeriodInTicks,
 									const UBaseType_t uxAutoReload,
 									void * const pvTimerID,
 									TimerCallbackFunction_t pxCallbackFunction,
-									Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+									Timer_t *pxNewTimer ) PRIVILEGED_FUNCTION;
 /*-----------------------------------------------------------*/
 
 BaseType_t xTimerCreateTimerTask( void )
@@ -276,7 +282,7 @@ BaseType_t xReturn = pdFAIL;
 
 			vApplicationGetTimerTaskMemory( &pxTimerTaskTCBBuffer, &pxTimerTaskStackBuffer, &ulTimerTaskStackSize );
 			xTimerTaskHandle = xTaskCreateStatic(	prvTimerTask,
-													"Tmr Svc",
+													configTIMER_SERVICE_TASK_NAME,
 													ulTimerTaskStackSize,
 													NULL,
 													( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
@@ -291,7 +297,7 @@ BaseType_t xReturn = pdFAIL;
 		#else
 		{
 			xReturn = xTaskCreate(	prvTimerTask,
-									"Tmr Svc",
+									configTIMER_SERVICE_TASK_NAME,
 									configTIMER_TASK_STACK_DEPTH,
 									NULL,
 									( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
@@ -311,11 +317,11 @@ BaseType_t xReturn = pdFAIL;
 
 #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
 
-	TimerHandle_t xTimerCreate(	const char * const pcTimerName,
+	TimerHandle_t xTimerCreate(	const char * const pcTimerName,			/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 								const TickType_t xTimerPeriodInTicks,
 								const UBaseType_t uxAutoReload,
 								void * const pvTimerID,
-								TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+								TimerCallbackFunction_t pxCallbackFunction )
 	{
 	Timer_t *pxNewTimer;
 
@@ -343,12 +349,12 @@ BaseType_t xReturn = pdFAIL;
 
 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
 
-	TimerHandle_t xTimerCreateStatic(	const char * const pcTimerName,
+	TimerHandle_t xTimerCreateStatic(	const char * const pcTimerName,		/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 										const TickType_t xTimerPeriodInTicks,
 										const UBaseType_t uxAutoReload,
 										void * const pvTimerID,
 										TimerCallbackFunction_t pxCallbackFunction,
-										StaticTimer_t *pxTimerBuffer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+										StaticTimer_t *pxTimerBuffer )
 	{
 	Timer_t *pxNewTimer;
 
@@ -356,7 +362,7 @@ BaseType_t xReturn = pdFAIL;
 		{
 			/* Sanity check that the size of the structure used to declare a
 			variable of type StaticTimer_t equals the size of the real timer
-			structures. */
+			structure. */
 			volatile size_t xSize = sizeof( StaticTimer_t );
 			configASSERT( xSize == sizeof( Timer_t ) );
 		}
@@ -385,12 +391,12 @@ BaseType_t xReturn = pdFAIL;
 #endif /* configSUPPORT_STATIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
-static void prvInitialiseNewTimer(	const char * const pcTimerName,
+static void prvInitialiseNewTimer(	const char * const pcTimerName,			/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
 									const TickType_t xTimerPeriodInTicks,
 									const UBaseType_t uxAutoReload,
 									void * const pvTimerID,
 									TimerCallbackFunction_t pxCallbackFunction,
-									Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
+									Timer_t *pxNewTimer )
 {
 	/* 0 is not a valid value for xTimerPeriodInTicks. */
 	configASSERT( ( xTimerPeriodInTicks > 0 ) );
@@ -760,7 +766,7 @@ TickType_t xTimeNow;
 			software timer. */
 			pxTimer = xMessage.u.xTimerParameters.pxTimer;
 
-			if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE )
+			if( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) == pdFALSE ) /*lint !e961. The cast is only redundant when NULL is passed into the macro. */
 			{
 				/* The timer is in a list, remove it. */
 				( void ) uxListRemove( &( pxTimer->xTimerListItem ) );
@@ -945,10 +951,10 @@ static void prvCheckForValidListAndQueue( void )
 			{
 				/* The timer queue is allocated statically in case
 				configSUPPORT_DYNAMIC_ALLOCATION is 0. */
-				static StaticQueue_t xStaticTimerQueue;
-				static uint8_t ucStaticTimerQueueStorage[ configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ];
+				static StaticQueue_t xStaticTimerQueue; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
+				static uint8_t ucStaticTimerQueueStorage[ ( size_t ) configTIMER_QUEUE_LENGTH * sizeof( DaemonTaskMessage_t ) ]; /*lint !e956 Ok to declare in this manner to prevent additional conditional compilation guards in other locations. */
 
-				xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );
+				xTimerQueue = xQueueCreateStatic( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, ( UBaseType_t ) sizeof( DaemonTaskMessage_t ), &( ucStaticTimerQueueStorage[ 0 ] ), &xStaticTimerQueue );
 			}
 			#else
 			{
@@ -991,7 +997,7 @@ Timer_t *pxTimer = ( Timer_t * ) xTimer;
 		/* Checking to see if it is in the NULL list in effect checks to see if
 		it is referenced from either the current or the overflow timer lists in
 		one go, but the logic has to be reversed, hence the '!'. */
-		xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) );
+		xTimerIsInActiveList = ( BaseType_t ) !( listIS_CONTAINED_WITHIN( NULL, &( pxTimer->xTimerListItem ) ) ); /*lint !e961. Cast is only redundant when NULL is passed into the macro. */
 	}
 	taskEXIT_CRITICAL();
 
diff --git a/README.md b/README.md
index 6f1a381..4c18c40 100644
--- a/README.md
+++ b/README.md
@@ -78,8 +78,8 @@ Current status is alpha quality, actively developed. AP STATION mode (ie wifi cl
 ## Open Source Components
 
 * [FreeRTOS](http://www.freertos.org/) V9.0.0
-* [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v1.4.1, modified via the [esp-lwip project](https://github.com/kadamski/esp-lwip) by @kadamski.
-* [newlib](https://github.com/projectgus/newlib-xtensa) v2.2.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS.
+* [lwIP](http://lwip.wikia.com/wiki/LwIP_Wiki) v2.0.3, with [some modifications](https://github.com/ourairquality/lwip/).
+* [newlib](https://github.com/ourairquality/newlib) v2.5.0, with patches for xtensa support and locking stubs for thread-safe operation on FreeRTOS.
 
 For details of how third party libraries are integrated, [see the wiki page](https://github.com/SuperHouse/esp-open-rtos/wiki/Third-Party-Libraries).
 
diff --git a/core/app_main.c b/core/app_main.c
index e56b0ab..fb72cac 100644
--- a/core/app_main.c
+++ b/core/app_main.c
@@ -214,8 +214,8 @@ void IRAM sdk_user_start(void) {
     memcpy(&sdk_g_ic.s, buf32, sizeof(struct sdk_g_ic_saved_st));
 
     // By default, put the sysparam region just below the config sectors at the
-    // top of the flash space
-    sysparam_addr = flash_size - (4 + DEFAULT_SYSPARAM_SECTORS) * sdk_flashchip.sector_size;
+    // top of the flash space, and allowing one extra sector spare.
+    sysparam_addr = flash_size - (5 + DEFAULT_SYSPARAM_SECTORS) * sdk_flashchip.sector_size;
     status = sysparam_init(sysparam_addr, flash_size);
     if (status == SYSPARAM_NOTFOUND) {
         status = sysparam_create_area(sysparam_addr, DEFAULT_SYSPARAM_SECTORS, false);
@@ -311,8 +311,8 @@ static void init_g_ic(void) {
     if (sdk_g_ic.s._unknown310 > 4) {
         sdk_g_ic.s._unknown310 = 4;
     }
-    if (sdk_g_ic.s._unknown1e4._unknown1e4 == 0xffffffff) {
-        bzero(&sdk_g_ic.s._unknown1e4, sizeof(sdk_g_ic.s._unknown1e4));
+    if (sdk_g_ic.s.sta_ssid.ssid_length == 0xffffffff) {
+        bzero(&sdk_g_ic.s.sta_ssid, sizeof(sdk_g_ic.s.sta_ssid));
         bzero(&sdk_g_ic.s.sta_password, sizeof(sdk_g_ic.s.sta_password));
     }
     sdk_g_ic.s.wifi_led_enable = 0;
diff --git a/core/esp_gpio.c b/core/esp_gpio.c
index a3011e1..359f828 100644
--- a/core/esp_gpio.c
+++ b/core/esp_gpio.c
@@ -58,17 +58,17 @@ void gpio_set_pullup(uint8_t gpio_num, bool enabled, bool enabled_during_sleep)
 
 static gpio_interrupt_handler_t gpio_interrupt_handlers[16] = { 0 };
 
-void __attribute__((weak)) IRAM gpio_interrupt_handler(void)
+void __attribute__((weak)) IRAM gpio_interrupt_handler(void *arg)
 {
     uint32_t status_reg = GPIO.STATUS;
     GPIO.STATUS_CLEAR = status_reg;
 
     uint8_t gpio_idx;
-    while((gpio_idx = __builtin_ffs(status_reg)))
+    while ((gpio_idx = __builtin_ffs(status_reg)))
     {
         gpio_idx--;
         status_reg &= ~BIT(gpio_idx);
-        if(FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
+        if (FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
             gpio_interrupt_handler_t handler = gpio_interrupt_handlers[gpio_idx];
             if (handler) {
                 handler(gpio_idx);
@@ -82,8 +82,8 @@ void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, g
     gpio_interrupt_handlers[gpio_num] = handler;
 
     GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
-    if(int_type != GPIO_INTTYPE_NONE) {
-        _xt_isr_attach(INUM_GPIO, gpio_interrupt_handler);
+    if (int_type != GPIO_INTTYPE_NONE) {
+        _xt_isr_attach(INUM_GPIO, gpio_interrupt_handler, NULL);
         _xt_isr_unmask(1<
 
-_xt_isr isr[16];
+typedef struct _xt_isr_entry_ {
+    _xt_isr handler;
+    void *arg;
+} _xt_isr_entry;
+
+_xt_isr_entry isr[16];
 
 bool esp_in_isr;
 
-void IRAM _xt_isr_attach(uint8_t i, _xt_isr func)
+void IRAM _xt_isr_attach(uint8_t i, _xt_isr func, void *arg)
 {
-    isr[i] = func;
+    isr[i].handler = func;
+    isr[i].arg = arg;
 }
 
 /* Generic ISR handler.
@@ -25,17 +31,20 @@ uint16_t IRAM _xt_isr_handler(uint16_t intset)
     esp_in_isr = true;
 
     /* WDT has highest priority (occasional WDT resets otherwise) */
-    if(intset & BIT(INUM_WDT)) {
+    if (intset & BIT(INUM_WDT)) {
         _xt_clear_ints(BIT(INUM_WDT));
-        isr[INUM_WDT]();
+        isr[INUM_WDT].handler(NULL);
         intset -= BIT(INUM_WDT);
     }
 
-    while(intset) {
+    while (intset) {
         uint8_t index = __builtin_ffs(intset) - 1;
         uint16_t mask = BIT(index);
         _xt_clear_ints(mask);
-        isr[index]();
+        _xt_isr handler = isr[index].handler;
+        if (handler) {
+            handler(isr[index].arg);
+        }
         intset -= mask;
     }
 
diff --git a/core/include/esp/gpio.h b/core/include/esp/gpio.h
index 9187087..85842aa 100644
--- a/core/include/esp/gpio.h
+++ b/core/include/esp/gpio.h
@@ -150,7 +150,7 @@ typedef void (* gpio_interrupt_handler_t)(uint8_t gpio_num);
  *
  *   Example:
  *
- *   void IRAM gpio_interrupt_handler(void) {
+ *   void IRAM gpio_interrupt_handler(void *arg) {
  *        // check GPIO.STATUS
  *        // write GPIO.STATUS_CLEAR
  *        // Do something when GPIO changes
diff --git a/core/include/esp/interrupts.h b/core/include/esp/interrupts.h
index 47594a2..5bdd833 100644
--- a/core/include/esp/interrupts.h
+++ b/core/include/esp/interrupts.h
@@ -35,19 +35,37 @@ typedef enum {
     INUM_TIMER_FRC2 = 10,
 } xt_isr_num_t;
 
-void sdk__xt_int_exit (void);
-void _xt_user_exit (void);
-void sdk__xt_tick_timer_init (void);
-void sdk__xt_timer_int(void);
+void sdk__xt_int_exit(void);
+void _xt_user_exit(void);
+void sdk__xt_tick_timer_init(void);
+void sdk__xt_timer_int(void *);
 void sdk__xt_timer_int1(void);
 
+/* The normal running level is 0.
+ * The system tick isr, timer frc2_isr, sv_isr etc  run at level 1.
+ * Debug exceptions run at level 2?
+ * The wdev nmi runs at level 3.
+ */
 static inline uint32_t _xt_get_intlevel(void)
 {
     uint32_t level;
-    __asm__ volatile("rsr %0, intlevel" : "=a"(level));
-    return level;
+    __asm__ volatile("rsr %0, ps" : "=a"(level));
+    return level & 0xf;
 }
 
+/*
+ * There are conflicting definitions for XCHAL_EXCM_LEVEL. Newlib
+ * defines it to be 1 and xtensa_rtos.h defines it to be 3. Don't want
+ * 3 as that is for the NMI and might want to check that the OS apis
+ * are not entered in level 3. Setting the interrupt level to 3 does
+ * not disable the NMI anyway. So set the level to 2.
+ */
+
+#ifdef XCHAL_EXCM_LEVEL
+#undef XCHAL_EXCM_LEVEL
+#define XCHAL_EXCM_LEVEL 2
+#endif
+
 /* Disable interrupts and return the old ps value, to pass into
    _xt_restore_interrupts later.
 
@@ -68,25 +86,27 @@ static inline void _xt_restore_interrupts(uint32_t new_ps)
     __asm__ volatile ("wsr %0, ps; rsync" :: "a" (new_ps));
 }
 
-/* ESPTODO: the mask/unmask functions aren't thread safe */
-
-static inline void _xt_isr_unmask(uint32_t unmask)
+static inline uint32_t _xt_isr_unmask(uint32_t unmask)
 {
+    uint32_t old_level = _xt_disable_interrupts();
     uint32_t intenable;
     asm volatile ("rsr %0, intenable" : "=a" (intenable));
-    intenable |= unmask;
-    asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
+    asm volatile ("wsr %0, intenable;" :: "a" (intenable | unmask));
+    _xt_restore_interrupts(old_level);
+    return intenable;
 }
 
-static inline void _xt_isr_mask (uint32_t mask)
+static inline uint32_t _xt_isr_mask(uint32_t mask)
 {
+    uint32_t old_level = _xt_disable_interrupts();
     uint32_t intenable;
     asm volatile ("rsr %0, intenable" : "=a" (intenable));
-    intenable &= ~mask;
-    asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
+    asm volatile ("wsr %0, intenable;" :: "a" (intenable & ~mask));
+    _xt_restore_interrupts(old_level);
+    return intenable;
 }
 
-static inline uint32_t _xt_read_ints (void)
+static inline uint32_t _xt_read_ints(void)
 {
     uint32_t interrupt;
     asm volatile ("rsr %0, interrupt" : "=a" (interrupt));
@@ -98,9 +118,7 @@ static inline void _xt_clear_ints(uint32_t mask)
     asm volatile ("wsr %0, intclear; esync" :: "a" (mask));
 }
 
-typedef void (* _xt_isr)(void);
-/* This function is implemeneted in FreeRTOS port.c at the moment,
-   should be moved or converted to an inline */
-void        _xt_isr_attach (uint8_t i, _xt_isr func);
+typedef void (* _xt_isr)(void *arg);
+void _xt_isr_attach (uint8_t i, _xt_isr func, void *arg);
 
 #endif
diff --git a/core/include/sdk_internal.h b/core/include/sdk_internal.h
index 1847eef..a4e21c6 100644
--- a/core/include/sdk_internal.h
+++ b/core/include/sdk_internal.h
@@ -14,25 +14,25 @@
 // 'info' is declared in app_main.o at .bss+0x4
 
 struct sdk_info_st {
-    ip_addr_t softap_ipaddr;    // 0x00
-    ip_addr_t softap_netmask;   // 0x04
-    ip_addr_t softap_gw;        // 0x08
-    ip_addr_t sta_ipaddr;       // 0x0c
-    ip_addr_t sta_netmask;      // 0x10
-    ip_addr_t sta_gw;           // 0x14
+    ip4_addr_t softap_ipaddr;    // 0x00
+    ip4_addr_t softap_netmask;   // 0x04
+    ip4_addr_t softap_gw;        // 0x08
+    ip4_addr_t sta_ipaddr;       // 0x0c
+    ip4_addr_t sta_netmask;      // 0x10
+    ip4_addr_t sta_gw;           // 0x14
     uint8_t softap_mac_addr[6]; // 0x18
     uint8_t sta_mac_addr[6];    // 0x1e
 };
 
 
-struct _unknown_info1 {
+struct wl_channel {
     uint8_t _unknown00;
     uint8_t _unknown01;
     uint8_t _unknown02;
     uint8_t _unknown03;
     uint8_t _unknown04;
     uint8_t _unknown05;
-    uint8_t channel; // eagle_auth_done
+    uint8_t num; // eagle_auth_done
 };
 
 
@@ -83,7 +83,7 @@ struct _unknown_wpa1 {
 };
 
 
-struct sdk_netif_conninfo {
+struct sdk_cnx_node {
     uint8_t mac_addr[6];
     uint8_t _unknown07[2];
 
@@ -98,17 +98,19 @@ struct sdk_netif_conninfo {
 
     uint32_t _unknown1c[23];
 
-    struct _unknown_info1 *_unknown78; // eagle_auth_done
+    struct wl_channel *channel; // 0x78 eagle_auth_done
 
     uint32_t _unknown7c[8];
 
     uint16_t _unknown9c; // ieee80211_hostap. increases by one one each timer func called.
     uint16_t _unknown9e;
 
-    uint32_t _unknowna0[18];
+    uint32_t _unknowna0[17];
 
-    int8_t _unknowne8; //
-    int8_t _unknowne9; // ppInstallKey
+    void *_unknowne4;
+
+    uint8_t _unknowne8; //
+    uint8_t _unknowne9; // ppInstallKey
     int8_t _unknownea;
     int8_t _unknowneb;
 
@@ -128,9 +130,9 @@ struct sdk_g_ic_netif_info {
     uint32_t _unknown48;     // 0x48
     uint8_t _unknown4c;      // 0x4c
     uint8_t _unknown4d[59];  // 0x4d - 0x88
-    struct sdk_netif_conninfo *_unknown88;  // 0x88
+    struct sdk_cnx_node *_unknown88;  // 0x88
     uint32_t _unknown8c;     // 0x8c
-    struct sdk_netif_conninfo *conninfo[6]; // 0x90 - 0xa8
+    struct sdk_cnx_node *cnx_nodes[6]; // 0x90 - 0xa8
     uint8_t _unknowna8[12];  // 0xa8 - 0xb4
     struct _unknown_softap1 *_unknownb4;
     uint8_t statusb8;        // 0xb8 (arg of sta_status_set)
@@ -206,10 +208,9 @@ struct sdk_g_ic_volatile_st {
 };
 
 
-struct sdk_g_ic_unk0_st {
-    uint16_t _unknown1e4;  // sdk_wpa_config_profile
-    uint16_t _unknown1e6;  // sdk_wpa_config_profile
-    uint8_t sta_ssid[32];  // 0x1e8 Station ssid. Null terminated string.
+struct sdk_g_ic_ssid_with_length {
+    uint32_t ssid_length;  // 0x1e4 sdk_wpa_config_profile
+    uint8_t ssid[32];  // 0x1e8 Station ssid. Null terminated string.
 };
 
 // This is the portion of g_ic which is loaded/saved to the flash ROM, and thus
@@ -224,7 +225,8 @@ struct sdk_g_ic_saved_st {
     uint8_t wifi_led_gpio;
     uint8_t wifi_led_state;  // 0 or 1.
 
-    struct sdk_g_ic_unk0_st _unknown1e4;
+    // Current station ap config ssid and length.
+    struct sdk_g_ic_ssid_with_length sta_ssid; // 0x1e4
 
     uint8_t _unknown208;
     uint8_t _unknown209; // sdk_wpa_config_profile
@@ -260,7 +262,7 @@ struct sdk_g_ic_saved_st {
     uint8_t _unknown30d; // result of ieee80211_chan2ieee
     uint8_t _unknown30e;
     uint8_t _unknown30f;
-    uint8_t _unknown310; // count of entries in the softap conninfo array, less two.
+    uint8_t _unknown310; // count of entries in the softap cnx_node array, less two.
 
     uint8_t _unknown311[3];
 
@@ -320,7 +322,7 @@ struct esf_buf {
 _Static_assert(sizeof(struct sdk_info_st) == 0x24, "info_st is the wrong size!");
 _Static_assert(offsetof(struct sdk_info_st, sta_mac_addr) == 0x1e, "bad struct");
 
-_Static_assert(offsetof(struct _unknown_info1, channel) == 0x06, "bad struct");
+_Static_assert(offsetof(struct wl_channel, num) == 0x06, "bad struct");
 
 _Static_assert(sizeof(struct _unknown_softap2) == 0xcc, "_unknown_softap2 is the wrong size!");
 _Static_assert(offsetof(struct _unknown_softap2, _unknownb8) == 0xb8, "bad struct");
@@ -331,8 +333,8 @@ _Static_assert(offsetof(struct _unknown_softap1, _unknown18) == 0x18, "bad struc
 _Static_assert(sizeof(struct _unknown_wpa1) == 0x4c, "_unknown_wpa1 is the wrong size!");
 _Static_assert(offsetof(struct _unknown_wpa1, _unknown48) == 0x48, "bad struct");
 
-_Static_assert(offsetof(struct sdk_netif_conninfo, _unknown78) == 0x78, "bad struct");
-_Static_assert(offsetof(struct sdk_netif_conninfo, _unknown108) == 0x108, "bad struct");
+_Static_assert(offsetof(struct sdk_cnx_node, channel) == 0x78, "bad struct");
+_Static_assert(offsetof(struct sdk_cnx_node, _unknown108) == 0x108, "bad struct");
 
 _Static_assert(offsetof(struct sdk_g_ic_netif_info, started) == 0xbb, "bad struct");
 
@@ -340,7 +342,7 @@ _Static_assert(sizeof(struct sdk_g_ic_volatile_st) == 0x1d8, "sdk_g_ic_volatile_
 _Static_assert(offsetof(struct sdk_g_ic_volatile_st, _unknown1d5) == 0x1d5, "bad struct");
 
 _Static_assert(sizeof(struct sdk_g_ic_saved_st) == 0x370, "sdk_g_ic_saved_st is the wrong size!");
-_Static_assert(offsetof(struct sdk_g_ic_saved_st, _unknown1e4) == 0x1e4 - 0x1d8, "bad struct");
+_Static_assert(offsetof(struct sdk_g_ic_saved_st, sta_ssid) == 0x1e4 - 0x1d8, "bad struct");
 _Static_assert(offsetof(struct sdk_g_ic_saved_st, _unknown546) == 0x546 - 0x1d8, "bad struct");
 
 _Static_assert(sizeof(struct sdk_g_ic_st) == 0x548, "sdk_g_ic_st is the wrong size!");
@@ -357,21 +359,16 @@ _Static_assert(offsetof(struct esf_buf, length) == 0x16, "bad struct");
 // ieee80211_output_pbuf and perhaps elsewhere. The value is just passed through
 // lwip and and not used by lwip so just ensure this slot is at the expected
 // offset.
-_Static_assert(offsetof(struct netif, state) == 28, "netif->state offset wrong!");
+_Static_assert(offsetof(struct netif, state) == 4, "netif->state offset wrong!");
 
 // Some sdk uses of netif->hwaddr have been converted to source code, but many
 // remain, but the content of this slot should not change in future versions of
-// lwip, so just ensure it is at the expected offset.
-_Static_assert(offsetof(struct netif, hwaddr) == 41, "netif->hwaddr offset wrong!");
+// lwip, so just ensure it is at the expected offset. Note the sdk binary
+// libraries have been patched to move this offset from 41 to 42 to keep it
+// 16-bit aligned to keep lwip v2 happy.
+_Static_assert(offsetof(struct netif, hwaddr) == 8, "netif->hwaddr offset wrong!");
 
-// Most sdk uses of the netif->flags have been converted to source code. One
-// known sdk binary read of the flags remains in wl_cnx.o:sdk_cnx_sta_leave
-// which checks the NETIF_FLAG_DHCP flag. The NETIF_FLAG_DHCP has been removed
-// in lwip v2, so some lwip hacks are needed to handle this for now until
-// wl_cnx.o is converted so source code too.
-_Static_assert(offsetof(struct netif, flags) == 47, "netif->flags offset wrong!");
-
-_Static_assert(offsetof(struct pbuf, eb) == 16, "pbuf->eb offset wrong!");
+_Static_assert(offsetof(struct pbuf, esf_buf) == 16, "pbuf->esf_buf offset wrong!");
 
 
 /// Misc.
diff --git a/core/newlib_syscalls.c b/core/newlib_syscalls.c
index 146a010..d095ba9 100644
--- a/core/newlib_syscalls.c
+++ b/core/newlib_syscalls.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 extern void *xPortSupervisorStackPointer;
 
@@ -135,6 +136,14 @@ int _stat_r(struct _reent *r, const char *pathname, void *buf);
 __attribute__((weak, alias("syscall_returns_enosys"))) 
 off_t _lseek_r(struct _reent *r, int fd, off_t offset, int whence);
 
+__attribute__((weak, alias("_gettimeofday_r")))
+int _gettimeofday_r _PARAMS ((struct _reent *r, struct timeval *now, void *p)) {
+  now->tv_sec = 0;
+  now->tv_usec = 0;
+  errno = ENOSYS;
+  return -1;
+}
+
 /* Generic stub for any newlib syscall that fails with errno ENOSYS
    ("Function not implemented") and a return value equivalent to
    (int)-1. */
diff --git a/core/spiflash.c b/core/spiflash.c
index 386d7c9..764db11 100644
--- a/core/spiflash.c
+++ b/core/spiflash.c
@@ -133,7 +133,7 @@ static bool IRAM spi_write(uint32_t addr, uint8_t *dst, uint32_t size)
 
         uint32_t offset = write_bytes_to_page;
         uint32_t pages_to_write = (size - offset) / sdk_flashchip.page_size;
-        for (uint8_t i = 0; i != pages_to_write; i++) {
+        for (uint32_t i = 0; i < pages_to_write; i++) {
             if (!spi_write_page(&sdk_flashchip, addr + offset,
                         dst + offset, sdk_flashchip.page_size)) {
                 return false;
diff --git a/core/sysparam.c b/core/sysparam.c
index 126cfe0..27471a0 100644
--- a/core/sysparam.c
+++ b/core/sysparam.c
@@ -801,9 +801,13 @@ sysparam_status_t sysparam_get_bool(const char *key, bool *result) {
     do {
         if (binary) {
             if (data_len == 1) {  // int8 value
-                *result = (int8_t)(*buf) ? true : false;
+                uint8_t value;
+                memcpy(&value, buf, sizeof(value));
+                *result = value ? true : false;
             } else if (data_len == 4) {  // int32 value
-                *result = (int32_t)(*buf) ? true : false;
+                uint32_t value;
+                memcpy(&value, buf, sizeof(value));
+                *result = value ? true : false;
             } else {
                 status = SYSPARAM_PARSEFAILED;
             }
diff --git a/examples/access_point/access_point.c b/examples/access_point/access_point.c
index f8fcd50..20e9d88 100644
--- a/examples/access_point/access_point.c
+++ b/examples/access_point/access_point.c
@@ -1,11 +1,11 @@
-/* Very basic example showing usage of access point mode and the DHCP server.
-
-   The ESP in the example runs a telnet server on 172.16.0.1 (port 23) that
-   outputs some status information if you connect to it, then closes
-   the connection.
-
-   This example code is in the public domain.
-*/
+/**
+ * Very basic example showing usage of access point mode and the DHCP server.
+ * The ESP in the example runs a telnet server on 172.16.0.1 (port 23) that
+ * outputs some status information if you connect to it, then closes
+ * the connection.
+ *
+ * This example code is in the public domain.
+ */
 #include 
 
 #include 
@@ -36,62 +36,55 @@ void user_init(void)
     IP4_ADDR(&ap_ip.netmask, 255, 255, 0, 0);
     sdk_wifi_set_ip_info(1, &ap_ip);
 
-    struct sdk_softap_config ap_config = {
-        .ssid = AP_SSID,
-        .ssid_hidden = 0,
-        .channel = 3,
-        .ssid_len = strlen(AP_SSID),
-        .authmode = AUTH_WPA_WPA2_PSK,
-        .password = AP_PSK,
-        .max_connection = 3,
-        .beacon_interval = 100,
-    };
+    struct sdk_softap_config ap_config = { .ssid = AP_SSID, .ssid_hidden = 0, .channel = 3, .ssid_len = strlen(AP_SSID), .authmode =
+            AUTH_WPA_WPA2_PSK, .password = AP_PSK, .max_connection = 3, .beacon_interval = 100, };
     sdk_wifi_softap_set_config(&ap_config);
 
-    ip_addr_t first_client_ip;
-    IP4_ADDR(&first_client_ip, 172, 16, 0, 2);
-    dhcpserver_start(&first_client_ip, 4);
-
     xTaskCreate(telnetTask, "telnetTask", 512, NULL, 2, NULL);
 }
 
 /* Telnet task listens on port 23, returns some status information and then closes
-   the connection if you connect to it.
-*/
+ the connection if you connect to it.
+ */
 static void telnetTask(void *pvParameters)
 {
-  struct netconn *nc = netconn_new (NETCONN_TCP);
-  if(!nc) {
-    printf("Status monitor: Failed to allocate socket.\r\n");
-    return;
-  }
-  netconn_bind(nc, IP_ADDR_ANY, TELNET_PORT);
-  netconn_listen(nc);
+    ip_addr_t first_client_ip;
+    IP4_ADDR(&first_client_ip, 172, 16, 0, 2);
+    dhcpserver_start(&first_client_ip, 4);
 
-  while(1) {
-    struct netconn *client = NULL;
-    err_t err = netconn_accept(nc, &client);
-
-    if ( err != ERR_OK ) {
-      if(client)
-	netconn_delete(client);
-      continue;
+    struct netconn *nc = netconn_new(NETCONN_TCP);
+    if (!nc)
+    {
+        printf("Status monitor: Failed to allocate socket.\r\n");
+        return;
     }
+    netconn_bind(nc, IP_ANY_TYPE, TELNET_PORT);
+    netconn_listen(nc);
 
-    ip_addr_t client_addr;
-    uint16_t port_ignore;
-    netconn_peer(client, &client_addr, &port_ignore);
+    while (1)
+    {
+        struct netconn *client = NULL;
+        err_t err = netconn_accept(nc, &client);
 
-    char buf[80];
-    snprintf(buf, sizeof(buf), "Uptime %d seconds\r\n",
-	     xTaskGetTickCount()*portTICK_PERIOD_MS/1000);
-    netconn_write(client, buf, strlen(buf), NETCONN_COPY);
-    snprintf(buf, sizeof(buf), "Free heap %d bytes\r\n", (int)xPortGetFreeHeapSize());
-    netconn_write(client, buf, strlen(buf), NETCONN_COPY);
-    snprintf(buf, sizeof(buf), "Your address is %d.%d.%d.%d\r\n\r\n",
-             ip4_addr1(&client_addr), ip4_addr2(&client_addr),
-             ip4_addr3(&client_addr), ip4_addr4(&client_addr));
-    netconn_write(client, buf, strlen(buf), NETCONN_COPY);
-    netconn_delete(client);
-  }
+        if (err != ERR_OK)
+        {
+            if (client)
+                netconn_delete(client);
+            continue;
+        }
+
+        ip_addr_t client_addr;
+        uint16_t port_ignore;
+        netconn_peer(client, &client_addr, &port_ignore);
+
+        char buf[80];
+        snprintf(buf, sizeof(buf), "Uptime %d seconds\r\n", xTaskGetTickCount() * portTICK_PERIOD_MS / 1000);
+        netconn_write(client, buf, strlen(buf), NETCONN_COPY);
+        snprintf(buf, sizeof(buf), "Free heap %d bytes\r\n", (int) xPortGetFreeHeapSize());
+        netconn_write(client, buf, strlen(buf), NETCONN_COPY);
+        char abuf[40];
+        snprintf(buf, sizeof(buf), "Your address is %s\r\n\r\n", ipaddr_ntoa_r(&client_addr, abuf, sizeof(abuf)));
+        netconn_write(client, buf, strlen(buf), NETCONN_COPY);
+        netconn_delete(client);
+    }
 }
diff --git a/examples/blink_timers/blink_timers.c b/examples/blink_timers/blink_timers.c
index 177cff3..bef887d 100644
--- a/examples/blink_timers/blink_timers.c
+++ b/examples/blink_timers/blink_timers.c
@@ -17,13 +17,13 @@ const int freq_frc2 = 10;
 static volatile uint32_t frc1_count;
 static volatile uint32_t frc2_count;
 
-void frc1_interrupt_handler(void)
+void frc1_interrupt_handler(void *arg)
 {
     frc1_count++;
     gpio_toggle(gpio_frc1);
 }
 
-void frc2_interrupt_handler(void)
+void frc2_interrupt_handler(void *arg)
 {
     /* FRC2 needs the match register updated on each timer interrupt */
     timer_set_frequency(FRC2, freq_frc2);
@@ -47,8 +47,8 @@ void user_init(void)
     timer_set_run(FRC2, false);
 
     /* set up ISRs */
-    _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
-    _xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler);
+    _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
+    _xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler, NULL);
 
     /* configure timer frequencies */
     timer_set_frequency(FRC1, freq_frc1);
diff --git a/examples/experiments/timers/timers.c b/examples/experiments/timers/timers.c
index a2e5e66..c889643 100644
--- a/examples/experiments/timers/timers.c
+++ b/examples/experiments/timers/timers.c
@@ -97,7 +97,7 @@ void timerRegTask(void *pvParameters)
     }
 }
 
-IRAM void frc1_handler(void)
+IRAM void frc1_handler(void *arg)
 {
     frc1_handler_call_count++;
     frc1_last_count_val = TIMER(0).COUNT;
@@ -106,7 +106,7 @@ IRAM void frc1_handler(void)
     //TIMER_FRC1_MATCH_REG = frc1_last_count_val + 0x100000;
 }
 
-void frc2_handler(void)
+void frc2_handler(void *arg)
 {
     frc2_handler_call_count++;
     frc2_last_count_val = TIMER(1).COUNT;
@@ -127,9 +127,9 @@ void user_init(void)
     TIMER(1).LOAD = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256);
 
     DPORT.INT_ENABLE |= DPORT_INT_ENABLE_TIMER0 | DPORT_INT_ENABLE_TIMER1;
-    _xt_isr_attach(INUM_TIMER_FRC1, frc1_handler);
+    _xt_isr_attach(INUM_TIMER_FRC1, frc1_handler, NULL);
     _xt_isr_unmask(1<ai_addr)->sin_addr;
-        printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(*addr));
+
+#if LWIP_IPV6
+        {
+            struct netif *netif = sdk_system_get_netif(0);
+            int i;
+            for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
+                printf("  ip6 %d state %x\n", i, netif_ip6_addr_state(netif, i));
+                if (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, i)))
+                    printf("  ip6 addr %d = %s\n", i, ip6addr_ntoa(netif_ip6_addr(netif, i)));
+            }
+        }
+#endif
+
+        struct sockaddr *sa = res->ai_addr;
+        if (sa->sa_family == AF_INET) {
+            printf("DNS lookup succeeded. IP=%s\r\n", inet_ntoa(((struct sockaddr_in *)sa)->sin_addr));
+        }
+#if LWIP_IPV6
+        if (sa->sa_family == AF_INET6) {
+            printf("DNS lookup succeeded. IP=%s\r\n", inet6_ntoa(((struct sockaddr_in6 *)sa)->sin6_addr));
+        }
+#endif
 
         int s = socket(res->ai_family, res->ai_socktype, 0);
         if(s < 0) {
@@ -75,8 +94,10 @@ void http_get_task(void *pvParameters)
         freeaddrinfo(res);
 
         const char *req =
-            "GET "WEB_URL"\r\n"
+            "GET "WEB_PATH" HTTP/1.1\r\n"
+            "Host: "WEB_SERVER"\r\n"
             "User-Agent: esp-open-rtos/0.1 esp8266\r\n"
+            "Connection: close\r\n"
             "\r\n";
         if (write(s, req, strlen(req)) < 0) {
             printf("... socket send failed\r\n");
@@ -126,6 +147,6 @@ void user_init(void)
     sdk_wifi_set_opmode(STATION_MODE);
     sdk_wifi_station_set_config(&config);
 
-    xTaskCreate(&http_get_task, "get_task", 256, NULL, 2, NULL);
+    xTaskCreate(&http_get_task, "get_task", 384, NULL, 2, NULL);
 }
 
diff --git a/examples/i2s_audio/i2s_audio_example.c b/examples/i2s_audio/i2s_audio_example.c
index 1972692..7b48c02 100644
--- a/examples/i2s_audio/i2s_audio_example.c
+++ b/examples/i2s_audio/i2s_audio_example.c
@@ -88,7 +88,7 @@ static inline void init_descriptors_list()
 }
 
 // DMA interrupt handler. It is called each time a DMA block is finished processing.
-static void dma_isr_handler(void)
+static void dma_isr_handler(void *args)
 {
     portBASE_TYPE task_awoken = pdFALSE;
 
@@ -168,7 +168,7 @@ void play_task(void *pvParameters)
 
     i2s_pins_t i2s_pins = {.data = true, .clock = true, .ws = true};
 
-    i2s_dma_init(dma_isr_handler, clock_div, i2s_pins);
+    i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
 
     while (1) {
         init_descriptors_list();
diff --git a/examples/sysparam_editor/Makefile b/examples/sysparam_editor/Makefile
index a774b68..f63e4e5 100644
--- a/examples/sysparam_editor/Makefile
+++ b/examples/sysparam_editor/Makefile
@@ -8,7 +8,7 @@ include ../../common.mk
 # `make dump-flash` can be used to view the current contents of the sysparam
 # regions in flash.
 dump-flash:
-	esptool.py read_flash 0x1f8000 8192 r1.bin
+	esptool.py read_flash 0x1f7000 8192 r1.bin
 	hexdump -C r1.bin
-	esptool.py read_flash 0x1fa000 8192 r2.bin
+	esptool.py read_flash 0x1f9000 8192 r2.bin
 	hexdump -C r2.bin
diff --git a/examples/sysparam_editor/sysparam_editor.c b/examples/sysparam_editor/sysparam_editor.c
index 0b58efd..29bf78e 100644
--- a/examples/sysparam_editor/sysparam_editor.c
+++ b/examples/sysparam_editor/sysparam_editor.c
@@ -45,7 +45,7 @@ size_t tty_readline(char *buffer, size_t buf_size, bool echo) {
 
     while (true) {
         c = getchar();
-        if (c == '\r') {
+        if (c == '\r' || c == '\n') {
             if (echo) putchar('\n');
             break;
         } else if (c == '\b' || c == 0x7f) {
@@ -173,7 +173,7 @@ void sysparam_editor_task(void *pvParameters) {
         // stuff, so if the user uses this utility to reformat it, it will put
         // it somewhere the system will find it later
         num_sectors = DEFAULT_SYSPARAM_SECTORS;
-        base_addr = sdk_flashchip.chip_size - (4 + num_sectors) * sdk_flashchip.sector_size;
+        base_addr = sdk_flashchip.chip_size - (5 + num_sectors) * sdk_flashchip.sector_size;
     }
     while (true) {
         printf("==> ");
@@ -246,5 +246,7 @@ void user_init(void)
 {
     uart_set_baud(0, 115200);
 
+    sdk_wifi_set_opmode(NULL_MODE);
+
     xTaskCreate(sysparam_editor_task, "sysparam_editor_task", 512, NULL, 2, NULL);
 }
diff --git a/examples/tcp_non_blocking/Makefile b/examples/tcp_non_blocking/Makefile
new file mode 100644
index 0000000..c88b576
--- /dev/null
+++ b/examples/tcp_non_blocking/Makefile
@@ -0,0 +1,5 @@
+# Makefile for tcp_non_blocking example
+PROGRAM=tcp_non_blocking
+EXTRA_COMPONENTS=extras/dhcpserver
+
+include ../../common.mk
diff --git a/examples/tcp_non_blocking/tcp_non_blocking.c b/examples/tcp_non_blocking/tcp_non_blocking.c
new file mode 100644
index 0000000..4e35aa2
--- /dev/null
+++ b/examples/tcp_non_blocking/tcp_non_blocking.c
@@ -0,0 +1,203 @@
+/*
+   The ESP in the example runs a echo server on 172.16.0.1 (port 50 and 100 ) that
+   outputs information about your ip/port then echo all text you write.
+   It is manage multiple connection and multiple port with one task.
+
+   This example code is in the public domain.
+ */
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define AP_SSID "esp-open-rtos AP"
+#define AP_PSK "esp-open-rtos"
+#define ECHO_PORT_1 50
+#define ECHO_PORT_2 100
+#define EVENTS_QUEUE_SIZE 10
+
+#ifdef CALLBACK_DEBUG
+#define debug(s, ...) printf("%s: " s "\n", "Cb:", ## __VA_ARGS__)
+#else
+#define debug(s, ...)
+#endif
+
+QueueHandle_t xQueue_events;
+typedef struct {
+    struct netconn *nc ;
+    uint8_t type ;
+} netconn_events;
+
+/*
+ * This function will be call in Lwip in each event on netconn
+ */
+static void netCallback(struct netconn *conn, enum netconn_evt evt, uint16_t length)
+{
+    //Show some callback information (debug)
+    debug("sock:%u\tsta:%u\tevt:%u\tlen:%u\ttyp:%u\tfla:%02X\terr:%d", \
+            (uint32_t)conn,conn->state,evt,length,conn->type,conn->flags,conn->last_err);
+
+    netconn_events events ;
+
+    //If netconn got error, it is close or deleted, dont do treatments on it.
+    if (conn->pending_err)
+    {
+        return;
+    }
+    //Treatments only on rcv events.
+    switch (evt) {
+    case NETCONN_EVT_RCVPLUS:
+        events.nc = conn ;
+        events.type = evt ;
+        break;
+    default:
+        return;
+        break;
+    }
+
+    //Send the event to the queue
+    xQueueSend(xQueue_events, &events, 1000);
+
+}
+
+/*
+ *  Initialize a server netconn and listen port
+ */
+static void set_tcp_server_netconn(struct netconn **nc, uint16_t port, netconn_callback callback)
+{
+    if(nc == NULL)
+    {
+        printf("%s: netconn missing .\n",__FUNCTION__);
+        return;
+    }
+    *nc = netconn_new_with_callback(NETCONN_TCP, netCallback);
+    if(!*nc) {
+        printf("Status monitor: Failed to allocate netconn.\n");
+        return;
+    }
+    netconn_set_nonblocking(*nc,NETCONN_FLAG_NON_BLOCKING);
+    //netconn_set_recvtimeout(*nc, 10);
+    netconn_bind(*nc, IP_ADDR_ANY, port);
+    netconn_listen(*nc);
+}
+
+/*
+ *  Close and delete a socket properly
+ */
+static void close_tcp_netconn(struct netconn *nc)
+{
+    nc->pending_err=ERR_CLSD; //It is hacky way to be sure than callback will don't do treatment on a netconn closed and deleted
+    netconn_close(nc);
+    netconn_delete(nc);
+}
+
+/*
+ *  This task manage each netconn connection without block anything
+ */
+static void nonBlockingTCP(void *pvParameters)
+{
+
+    struct netconn *nc = NULL; // To create servers
+
+    set_tcp_server_netconn(&nc, ECHO_PORT_1, netCallback);
+    printf("Server netconn %u ready on port %u.\n",(uint32_t)nc, ECHO_PORT_1);
+    set_tcp_server_netconn(&nc, ECHO_PORT_2, netCallback);
+    printf("Server netconn %u ready on port %u.\n",(uint32_t)nc, ECHO_PORT_2);
+
+    struct netbuf *netbuf = NULL; // To store incoming Data
+    struct netconn *nc_in = NULL; // To accept incoming netconn
+    //
+    char buf[50];
+    char* buffer;
+    uint16_t len_buf;
+
+    while(1) {
+
+        netconn_events events;
+        xQueueReceive(xQueue_events, &events, portMAX_DELAY); // Wait here an event on netconn
+
+        if (events.nc->state == NETCONN_LISTEN) // If netconn is a server and receive incoming event on it
+        {
+            printf("Client incoming on server %u.\n", (uint32_t)events.nc);
+            int err = netconn_accept(events.nc, &nc_in);
+            if (err != ERR_OK)
+            {
+                if(nc_in)
+                    netconn_delete(nc_in);
+            }
+            printf("New client is %u.\n",(uint32_t)nc_in);
+            ip_addr_t client_addr; //Address port
+            uint16_t client_port; //Client port
+            netconn_peer(nc_in, &client_addr, &client_port);
+            snprintf(buf, sizeof(buf), "Your address is %d.%d.%d.%d:%u.\r\n",
+                    ip4_addr1(&client_addr), ip4_addr2(&client_addr),
+                    ip4_addr3(&client_addr), ip4_addr4(&client_addr),
+                    client_port);
+            netconn_write(nc_in, buf, strlen(buf), NETCONN_COPY);
+        }
+        else if(events.nc->state != NETCONN_LISTEN) // If netconn is the client and receive data
+        {
+            if ((netconn_recv(events.nc, &netbuf)) == ERR_OK) // data incoming ?
+            {
+                do
+                {
+                    netbuf_data(netbuf, (void*)&buffer, &len_buf);
+                    netconn_write(events.nc, buffer, strlen(buffer), NETCONN_COPY);
+                    printf("Client %u send: %s\n",(uint32_t)events.nc,buffer);
+                }
+                while (netbuf_next(netbuf) >= 0);
+                netbuf_delete(netbuf);
+            }
+            else
+            {
+                close_tcp_netconn(events.nc);
+                printf("Error read netconn %u, close it \n",(uint32_t)events.nc);
+            }
+        }
+    }
+}
+
+void user_init(void)
+{
+    uart_set_baud(0, 115200);
+    sdk_os_delay_us(500); // Wait UART
+    printf("SDK version:%s\n", sdk_system_get_sdk_version());
+
+    sdk_wifi_set_opmode(SOFTAP_MODE);
+    struct ip_info ap_ip;
+    IP4_ADDR(&ap_ip.ip, 172, 16, 0, 1);
+    IP4_ADDR(&ap_ip.gw, 0, 0, 0, 0);
+    IP4_ADDR(&ap_ip.netmask, 255, 255, 0, 0);
+    sdk_wifi_set_ip_info(1, &ap_ip);
+
+    struct sdk_softap_config ap_config = {
+            .ssid = AP_SSID,
+            .ssid_hidden = 0,
+            .channel = 3,
+            .ssid_len = strlen(AP_SSID),
+            .authmode = AUTH_WPA_WPA2_PSK,
+            .password = AP_PSK,
+            .max_connection = 3,
+            .beacon_interval = 100,
+    };
+    sdk_wifi_softap_set_config(&ap_config);
+
+    ip_addr_t first_client_ip;
+    IP4_ADDR(&first_client_ip, 172, 16, 0, 2);
+    dhcpserver_start(&first_client_ip, 4);
+    printf("DHCP started\n");
+
+    //Create a queue to store events on netconns
+    xQueue_events = xQueueCreate( EVENTS_QUEUE_SIZE, sizeof(netconn_events));
+
+    xTaskCreate(nonBlockingTCP, "lwiptest_noblock", 512, NULL, 2, NULL);
+}
diff --git a/examples/terminal/terminal.c b/examples/terminal/terminal.c
index 6f8b940..f25293a 100644
--- a/examples/terminal/terminal.c
+++ b/examples/terminal/terminal.c
@@ -94,18 +94,23 @@ static void gpiomon()
     int i = 0;
     printf("\n\n\nWelcome to gpiomon. Type 'help' for, well, help\n");
     printf("%% ");
+    fflush(stdout); // stdout is line buffered
     while(1) {
         if (read(0, (void*)&ch, 1)) { // 0 is stdin
             printf("%c", ch);
+            fflush(stdout);
             if (ch == '\n' || ch == '\r') {
                 cmd[i] = 0;
                 i = 0;
                 printf("\n");
                 handle_command((char*) cmd);
                 printf("%% ");
+                fflush(stdout);
             } else {
                 if (i < sizeof(cmd)) cmd[i++] = ch;
             }
+        } else {
+            printf("You will never see this print as read(...) is blocking\n");
         }
     }
 }
diff --git a/examples/tls_server/tls_server.c b/examples/tls_server/tls_server.c
index 1317785..8ecfa56 100644
--- a/examples/tls_server/tls_server.c
+++ b/examples/tls_server/tls_server.c
@@ -202,9 +202,8 @@ void tls_server_task(void *pvParameters)
         socklen_t peer_addr_len = sizeof(struct sockaddr_in);
         getpeername(client_ctx.fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
         unsigned char buf[256];
-        int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\nFree heap size is %d bytes\n",
-                          ip4_addr1(&peer_addr.sin_addr), ip4_addr2(&peer_addr.sin_addr),
-                          ip4_addr3(&peer_addr.sin_addr), ip4_addr4(&peer_addr.sin_addr),
+        int len = sprintf((char *) buf, "O hai, client " IPSTR ":%d\nFree heap size is %d bytes\n",
+                          IP2STR((ip4_addr_t *)&peer_addr.sin_addr.s_addr),
                           peer_addr.sin_port, xPortGetFreeHeapSize());
         while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
         {
diff --git a/examples/tls_server_bearssl/tls_server_bearssl.c b/examples/tls_server_bearssl/tls_server_bearssl.c
index 09632ae..b1e48dc 100644
--- a/examples/tls_server_bearssl/tls_server_bearssl.c
+++ b/examples/tls_server_bearssl/tls_server_bearssl.c
@@ -146,9 +146,8 @@ void tls_server_task(void *pvParameters)
 
         /* Prepare a message to the client */
         unsigned char buf[100];
-        int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\r\nFree heap size is %d bytes\r\n",
-                          ip4_addr1(&sa.sin_addr), ip4_addr2(&sa.sin_addr),
-                          ip4_addr3(&sa.sin_addr), ip4_addr4(&sa.sin_addr),
+        int len = sprintf((char *) buf, "O hai, client " IPSTR ":%d\r\nFree heap size is %d bytes\r\n",
+                          IP2STR((ip4_addr_t *)&sa.sin_addr.s_addr),
                           ntohs(sa.sin_port), xPortGetFreeHeapSize());
 
         /* Send the message and close the connection */
diff --git a/examples/upnp/lwipopts.h b/examples/upnp/lwipopts.h
index a82d3fc..56f45f2 100644
--- a/examples/upnp/lwipopts.h
+++ b/examples/upnp/lwipopts.h
@@ -1,464 +1,5 @@
-/*
- * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- *    this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- * 
- * Author: Simon Goldschmidt
- *
- */
-#ifndef __LWIPOPTS_H__
-#define __LWIPOPTS_H__
-
-#define LWIP_ESP                            1
-#define ESP_RTOS                            1
-#define PBUF_RSV_FOR_WLAN                   1
-#define EBUF_LWIP                           1
-#define ESP_TIMEWAIT_THRESHOLD              10000
-#define LWIP_TIMEVAL_PRIVATE                0
-
-#define TCP_WND (TCP_MSS * 2)
 
 #define LWIP_IGMP 1
-#include 
-#include 
-#define LWIP_RAND hwrand
 
-/*
-   -----------------------------------------------
-   ---------- Platform specific locking ----------
-   -----------------------------------------------
-*/
-/**
- * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
- * critical regions during buffer allocation, deallocation and memory
- * allocation and deallocation.
- */
-#define SYS_LIGHTWEIGHT_PROT        1
-
-/**
- * MEMCPY: override this if you have a faster implementation at hand than the
- * one included in your C library
- */
-#define MEMCPY(dst,src,len)             memcpy(dst,src,len)
-
-/**
- * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a
- * call to memcpy() if the length is known at compile time and is small.
- */
-#define SMEMCPY(dst,src,len)            memcpy(dst,src,len)
-
-/*
-   ------------------------------------
-   ---------- Memory options ----------
-   ------------------------------------
-*/
-/**
- * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library
- * instead of the lwip internal allocator. Can save code size if you
- * already use it.
- */
-#define MEM_LIBC_MALLOC        1
-
-/**
-* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator.
-* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution
-* speed and usage from interrupts!
-*/
-#define MEMP_MEM_MALLOC                 1
-
-/**
- * MEM_ALIGNMENT: should be set to the alignment of the CPU
- *    4 byte alignment -> #define MEM_ALIGNMENT 4
- *    2 byte alignment -> #define MEM_ALIGNMENT 2
- */
-#define MEM_ALIGNMENT           4
-
-/*
-   ------------------------------------------------
-   ---------- Internal Memory Pool Sizes ----------
-   ------------------------------------------------
-*/
-
-/*
-   --------------------------------
-   ---------- ARP options -------
-   --------------------------------
-*/
-/**
- * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address
- * resolution. By default, only the most recent packet is queued per IP address.
- * This is sufficient for most protocols and mainly reduces TCP connection
- * startup time. Set this to 1 if you know your application sends more than one
- * packet in a row to an IP address that is not in the ARP cache.
- */
-#define ARP_QUEUEING                    1
-
-/*
-   --------------------------------
-   ---------- IP options ----------
-   --------------------------------
-*/
-/**
- * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that
- * this option does not affect outgoing packet sizes, which can be controlled
- * via IP_FRAG.
- */
-#define IP_REASSEMBLY                   0
-
-/**
- * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note
- * that this option does not affect incoming packet sizes, which can be
- * controlled via IP_REASSEMBLY.
- */
-#define IP_FRAG                         1
-
-/**
- * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally)
- * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived
- * in this time, the whole packet is discarded.
- */
-#define IP_REASS_MAXAGE                 3
-
-/**
- * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled.
- * Since the received pbufs are enqueued, be sure to configure
- * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive
- * packets even if the maximum amount of fragments is enqueued for reassembly!
- */
-#define IP_REASS_MAX_PBUFS              10
-
-/*
-   ----------------------------------
-   ---------- ICMP options ----------
-   ----------------------------------
-*/
-
-/*
-   ---------------------------------
-   ---------- RAW options ----------
-   ---------------------------------
-*/
-
-/*
-   ----------------------------------
-   ---------- DHCP options ----------
-   ----------------------------------
-*/
-/**
- * LWIP_DHCP==1: Enable DHCP module.
- */
-#define LWIP_DHCP                       1
-
-#define LWIP_DHCP_BOOTP_FILE            0
-
-/*
-   ------------------------------------
-   ---------- AUTOIP options ----------
-   ------------------------------------
-*/
-/*
-   ----------------------------------
-   ---------- SNMP options ----------
-   ----------------------------------
-*/
-/*
-   ----------------------------------
-   ---------- IGMP options ----------
-   ----------------------------------
-*/
-/*
-   ----------------------------------
-   ---------- DNS options -----------
-   ----------------------------------
-*/
-/**
- * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS
- * transport.
- */
-#define LWIP_DNS                        1
-
-#define DNS_TABLE_SIZE 1
-#define DNS_MAX_NAME_LENGTH 128
-
-/*
-   ---------------------------------
-   ---------- UDP options ----------
-   ---------------------------------
-*/
-/*
-   ---------------------------------
-   ---------- TCP options ----------
-   ---------------------------------
-*/
-/**
- * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order.
- * Define to 0 if your device is low on memory.
- */
-#define TCP_QUEUE_OOSEQ                 0
-
-/*
- *     LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all
- *         events (accept, sent, etc) that happen in the system.
- *     LWIP_CALLBACK_API==1: The PCB callback function is called directly
- *         for the event. This is the default.
-*/
-#define TCP_MSS                         1460
-
-/**
- * TCP_MAXRTX: Maximum number of retransmissions of data segments.
- */
-#define TCP_MAXRTX                      6
-
-
-/**
- * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments.
- */
-#define TCP_SYNMAXRTX                   3
-
-/*
-   ----------------------------------
-   ---------- Pbuf options ----------
-   ----------------------------------
-*/
-
-/*
-   ------------------------------------------------
-   ---------- Network Interfaces options ----------
-   ------------------------------------------------
-*/
-/**
- * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data
- * to be sent into one single pbuf. This is for compatibility with DMA-enabled
- * MACs that do not support scatter-gather.
- * Beware that this might involve CPU-memcpy before transmitting that would not
- * be needed without this flag! Use this only if you need to!
- *
- * @todo: TCP and IP-frag do not work with this, yet:
- */
-#define LWIP_NETIF_TX_SINGLE_PBUF             1
-
-/*
-   ------------------------------------
-   ---------- LOOPIF options ----------
-   ------------------------------------
-*/
-
-/*
-   ------------------------------------
-   ---------- SLIPIF options ----------
-   ------------------------------------
-*/
-
-/*
-   ------------------------------------
-   ---------- Thread options ----------
-   ------------------------------------
-*/
-/**
- * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread.
- * The stack size value itself is platform-dependent, but is passed to
- * sys_thread_new() when the thread is created.
- */
-#define TCPIP_THREAD_STACKSIZE          512			//not ok:384 
-
-/**
- * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread.
- * The priority value itself is platform-dependent, but is passed to
- * sys_thread_new() when the thread is created.
- */
-#define TCPIP_THREAD_PRIO               (configMAX_PRIORITIES-5)
-
-/**
- * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages
- * The queue size value itself is platform-dependent, but is passed to
- * sys_mbox_new() when tcpip_init is called.
- */
-#define TCPIP_MBOX_SIZE                 16
-
-/**
- * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
- * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed
- * to sys_mbox_new() when the recvmbox is created.
- */
-#define DEFAULT_UDP_RECVMBOX_SIZE       6
-
-/**
- * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a
- * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed
- * to sys_mbox_new() when the recvmbox is created.
- */
-#define DEFAULT_TCP_RECVMBOX_SIZE       6
-
-/**
- * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections.
- * The queue size value itself is platform-dependent, but is passed to
- * sys_mbox_new() when the acceptmbox is created.
- */
-#define DEFAULT_ACCEPTMBOX_SIZE         6
-
-/*
-   ----------------------------------------------
-   ---------- Sequential layer options ----------
-   ----------------------------------------------
-*/
-
-/*
-   ------------------------------------
-   ---------- Socket options ----------
-   ------------------------------------
-*/
-/**
- * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
- * SO_SNDTIMEO processing.
- */
-#define LWIP_SO_SNDTIMEO                1
-
-/**
- * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
- * SO_RCVTIMEO processing.
- */
-#define LWIP_SO_RCVTIMEO                1
-
-/**
- * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
- * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
- * in seconds. (does not require sockets.c, and will affect tcp.c)
- */
-#define LWIP_TCP_KEEPALIVE              1
-
-/**
- * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing.
- */
-#define LWIP_SO_RCVBUF                  0
-
-/**
- * SO_REUSE==1: Enable SO_REUSEADDR option.
- */
-#define SO_REUSE                        1
-
-/*
-   ----------------------------------------
-   ---------- Statistics options ----------
-   ----------------------------------------
-*/
-
-/*
-   ---------------------------------
-   ---------- PPP options ----------
-   ---------------------------------
-*/
-
-/*
-   --------------------------------------
-   ---------- Checksum options ----------
-   --------------------------------------
-*/
-
-/*
-   ---------------------------------------
-   ---------- IPv6 options ---------------
-   ---------------------------------------
-*/
-
-/*
-   ---------------------------------------
-   ---------- Hook options ---------------
-   ---------------------------------------
-*/
-
-/*
-   ---------------------------------------
-   ---------- Debugging options ----------
-   ---------------------------------------
-*/
-
-// Uncomment this line, and set the individual debug options you want, for IP stack debug output
-//#define LWIP_DEBUG
-
-/**
- * ETHARP_DEBUG: Enable debugging in etharp.c.
- */
-#define ETHARP_DEBUG                    LWIP_DBG_OFF
-
-/**
- * PBUF_DEBUG: Enable debugging in pbuf.c.
- */
-#define PBUF_DEBUG                      LWIP_DBG_OFF
-
-/**
- * API_LIB_DEBUG: Enable debugging in api_lib.c.
- */
-#define API_LIB_DEBUG                   LWIP_DBG_OFF
-
-/**
- * SOCKETS_DEBUG: Enable debugging in sockets.c.
- */
-#define SOCKETS_DEBUG                   LWIP_DBG_OFF
-
-/**
- * IP_DEBUG: Enable debugging for IP.
- */
-#define IP_DEBUG                        LWIP_DBG_OFF
-
-/**
- * MEMP_DEBUG: Enable debugging in memp.c.
- */
-#define MEMP_DEBUG                      LWIP_DBG_OFF
-
-/**
- * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug.
- */
-#define TCP_INPUT_DEBUG                 LWIP_DBG_OFF
-
-/**
- * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions.
- */
-#define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
-
-/**
- * UDP_DEBUG: Enable debugging in udp.c.
- */
-#define UDP_DEBUG                     LWIP_DBG_OFF
-
-/**
- * ICMP_DEBUG: Enable debugging in udp.c.
- */
-#define ICMP_DEBUG                     LWIP_DBG_OFF
-
-/**
- * TCPIP_DEBUG: Enable debugging in tcpip.c.
- */
-#define TCPIP_DEBUG                     LWIP_DBG_OFF
-
-
-/**
- * DHCP_DEBUG: Enable debugging in dhcp.c.
- */
-#define DHCP_DEBUG                      LWIP_DBG_OFF
-
-#define LWIP_POSIX_SOCKETS_IO_NAMES     0
-
-#endif /* __LWIPOPTS_H__ */
+/* Use the defaults for everything else */
+#include_next 
diff --git a/examples/upnp/upnp.c b/examples/upnp/upnp.c
index a223d27..bb34cae 100644
--- a/examples/upnp/upnp.c
+++ b/examples/upnp/upnp.c
@@ -1,6 +1,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "upnp.h"
 
@@ -18,13 +19,13 @@ static const char* get_my_ip(void)
 }
 
 /**
-  * @brief This function joins a multicast group witht he specified ip/port
+  * @brief This function joins a multicast group with the specified ip/port
   * @param group_ip the specified multicast group ip
   * @param group_port the specified multicast port number
   * @param recv the lwip UDP callback
   * @retval udp_pcb* or NULL if joining failed
   */
-static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, void (* recv)(void * arg, struct udp_pcb * upcb, struct pbuf * p, struct ip_addr * addr, u16_t port))
+static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port))
 {
     bool status = false;
     struct udp_pcb *upcb;
@@ -36,7 +37,7 @@ static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, voi
             printf("Error, udp_new failed");
             break;
         }
-        udp_bind(upcb, IP_ADDR_ANY, group_port);
+        udp_bind(upcb, IP4_ADDR_ANY, group_port);
         struct netif* netif = sdk_system_get_netif(STATION_IF);
         if (!netif) {
             printf("Error, netif is null");
@@ -46,10 +47,10 @@ static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, voi
             netif->flags |= NETIF_FLAG_IGMP;
             igmp_start(netif);
         }
-        ip_addr_t ipgroup;
-        ipaddr_aton(group_ip, &ipgroup);
-        err_t err = igmp_joingroup(&netif->ip_addr, &ipgroup);
-        if(ERR_OK != err) {
+        ip4_addr_t ipgroup;
+        ip4addr_aton(group_ip, &ipgroup);
+        err_t err = igmp_joingroup_netif(netif, &ipgroup);
+        if (ERR_OK != err) {
             printf("Failed to join multicast group: %d", err);
             break;
         }
@@ -68,7 +69,7 @@ static struct udp_pcb* mcast_join_group(char *group_ip, uint16_t group_port, voi
     return upcb;
 }
 
-static void send(struct udp_pcb *upcb, struct ip_addr *addr, u16_t port)
+static void send_udp(struct udp_pcb *upcb, const ip_addr_t *addr, u16_t port)
 {
     struct pbuf *p;
     char msg[500];
@@ -110,14 +111,14 @@ static void send(struct udp_pcb *upcb, struct ip_addr *addr, u16_t port)
   * @param port the remote port from which the packet was received
   * @retval None
   */
-static void receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
+static void receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
 {
     if (p) {
         printf("Msg received port:%d len:%d\n", port, p->len);
         uint8_t *buf = (uint8_t*) p->payload;
         printf("Msg received port:%d len:%d\nbuf: %s\n", port, p->len, buf);
         
-        send(upcb, addr, port);
+        send_udp(upcb, addr, port);
 
         pbuf_free(p);
     }
diff --git a/examples/wificfg/.gitignore b/examples/wificfg/.gitignore
new file mode 100644
index 0000000..e067149
--- /dev/null
+++ b/examples/wificfg/.gitignore
@@ -0,0 +1 @@
+!local.mk
diff --git a/examples/wificfg/FreeRTOSConfig.h b/examples/wificfg/FreeRTOSConfig.h
new file mode 100644
index 0000000..baf25a4
--- /dev/null
+++ b/examples/wificfg/FreeRTOSConfig.h
@@ -0,0 +1,7 @@
+#define configUSE_TRACE_FACILITY 1
+#define configGENERATE_RUN_TIME_STATS 1
+#define portGET_RUN_TIME_COUNTER_VALUE() (RTC.COUNTER)
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() {}
+
+/* Use the defaults for everything else */
+#include_next
diff --git a/examples/wificfg/Makefile b/examples/wificfg/Makefile
new file mode 100644
index 0000000..2cbb996
--- /dev/null
+++ b/examples/wificfg/Makefile
@@ -0,0 +1,5 @@
+# Makefile for wificfg example
+PROGRAM=wificfg
+EXTRA_COMPONENTS=extras/dhcpserver extras/wificfg
+
+include ../../common.mk
diff --git a/examples/wificfg/content/index.html b/examples/wificfg/content/index.html
new file mode 100644
index 0000000..5512b7d
--- /dev/null
+++ b/examples/wificfg/content/index.html
@@ -0,0 +1,18 @@
+""
+""
+""
+""
+"",
+""
+""
+""
+""
+"",
+""
diff --git a/examples/wificfg/local.mk b/examples/wificfg/local.mk
new file mode 100644
index 0000000..c6c3129
--- /dev/null
+++ b/examples/wificfg/local.mk
@@ -0,0 +1 @@
+FLASH_SIZE ?= 32
diff --git a/examples/wificfg/wificfg.c b/examples/wificfg/wificfg.c
new file mode 100644
index 0000000..a90a9da
--- /dev/null
+++ b/examples/wificfg/wificfg.c
@@ -0,0 +1,94 @@
+/*
+ * Example Wifi configuration via an access point.
+ *
+ * Copyright (C) 2016 OurAirQuality.org
+ *
+ * Licensed under the Apache License, Version 2.0, January 2004 (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/
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS WITH THE SOFTWARE.
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "lwip/sockets.h"
+
+#include "wificfg/wificfg.h"
+
+#include "sysparam.h"
+
+static const char http_success_header[] = "HTTP/1.1 200 \r\n"
+    "Content-Type: text/html; charset=utf-8\r\n"
+    "Cache-Control: no-store\r\n"
+    "Transfer-Encoding: chunked\r\n"
+    "Connection: close\r\n"
+    "\r\n";
+static const char *http_index_content[] = {
+#include "content/index.html"
+};
+
+static int handle_index(int s, wificfg_method method,
+                        uint32_t content_length,
+                        wificfg_content_type content_type,
+                        char *buf, size_t len)
+{
+    if (wificfg_write_string(s, http_success_header) < 0) return -1;
+
+    if (method != HTTP_METHOD_HEAD) {
+        if (wificfg_write_string_chunk(s, http_index_content[0], buf, len) < 0) return -1;
+        if (wificfg_write_html_title(s, buf, len, "Home") < 0) return -1;
+        if (wificfg_write_string_chunk(s, http_index_content[1], buf, len) < 0) return -1;
+
+        socklen_t addr_len;
+        struct sockaddr addr;
+        addr_len = sizeof(addr);
+        getpeername(s, (struct sockaddr*)&addr, &addr_len);
+
+        if (wificfg_write_string_chunk(s, "
", buf, len) < 0) return -1; + if (addr.sa_family == AF_INET) { + struct sockaddr_in *sa = (struct sockaddr_in *)&addr; + if (wificfg_write_string_chunk(s, "
Peer address
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR " : %d
", + IP2STR((ip4_addr_t *)&sa->sin_addr.s_addr), ntohs(sa->sin_port)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, "
", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_index_content[2], buf, len) < 0) return -1; + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +static const wificfg_dispatch dispatch_list[] = { + {"/", HTTP_METHOD_GET, handle_index, false}, + {"/index.html", HTTP_METHOD_GET, handle_index, false}, + {NULL, HTTP_METHOD_ANY, NULL} +}; + +void user_init(void) +{ + uart_set_baud(0, 115200); + printf("SDK version:%s\n", sdk_system_get_sdk_version()); + + sdk_wifi_set_sleep_type(WIFI_SLEEP_MODEM); + + wificfg_init(80, dispatch_list); +} diff --git a/examples/ws2812_i2s/ws2812_i2s_colour_loop.c b/examples/ws2812_i2s/ws2812_i2s_colour_loop.c index 05f47c4..c5b5411 100644 --- a/examples/ws2812_i2s/ws2812_i2s_colour_loop.c +++ b/examples/ws2812_i2s/ws2812_i2s_colour_loop.c @@ -17,7 +17,7 @@ #include "ws2812_i2s/ws2812_i2s.h" -const uint32_t led_number = 60; +const uint32_t led_number = 12; const uint32_t tail_fade_factor = 2; const uint32_t tail_length = 8; @@ -41,7 +41,7 @@ static int fix_index(int index) static ws2812_pixel_t next_colour() { - ws2812_pixel_t colour = {0, 0, 0}; + ws2812_pixel_t colour = {0, 0, 0, 0}; colour.red = rand() % 256; colour.green = rand() % 256; colour.blue = rand() % 256; @@ -54,7 +54,7 @@ static void demo(void *pvParameters) ws2812_pixel_t pixels[led_number]; int head_index = 0; - ws2812_i2s_init(led_number); + ws2812_i2s_init(led_number, PIXEL_RGB); memset(pixels, 0, sizeof(ws2812_pixel_t) * led_number); @@ -69,8 +69,8 @@ static void demo(void *pvParameters) memset(&pixels[fix_index(head_index - tail_length)], 0, sizeof(ws2812_pixel_t)); - ws2812_i2s_update(pixels); - vTaskDelay(20 / portTICK_PERIOD_MS); + ws2812_i2s_update(pixels, PIXEL_RGB); + vTaskDelay(50 / portTICK_PERIOD_MS); } } } @@ -78,6 +78,14 @@ static void demo(void *pvParameters) void user_init(void) { uart_set_baud(0, 115200); + struct sdk_station_config config = { + .ssid = "Loading...", + .password = "morays59924_howitzer", + }; + + /* required to call wifi_set_opmode before station_set_config */ + sdk_wifi_set_opmode(STATION_MODE); + sdk_wifi_station_set_config(&config); xTaskCreate(&demo, "ws2812_i2s", 256, NULL, 10, NULL); } diff --git a/extras/bmp180/bmp180.c b/extras/bmp180/bmp180.c index 2cf513e..d7d4330 100644 --- a/extras/bmp180/bmp180.c +++ b/extras/bmp180/bmp180.c @@ -152,7 +152,7 @@ bool bmp180_measure(i2c_dev_t *dev, bmp180_constants_t *c, int32_t *temperature, if (!temperature && !pressure) return false; - // Temperature is always needed, allso required for pressure only. + // Temperature is always needed, also required for pressure only. // // Calculation taken from BMP180 Datasheet int32_t UT, X1, X2, B5; diff --git a/extras/dhcpserver/dhcpserver.c b/extras/dhcpserver/dhcpserver.c index d87daab..6b9655c 100644 --- a/extras/dhcpserver/dhcpserver.c +++ b/extras/dhcpserver/dhcpserver.c @@ -14,18 +14,28 @@ * BSD Licensed as described in the file LICENSE */ #include +#include #include #include #include #include +#include "esplibs/libmain.h" + +#if (DHCP_DEBUG == LWIP_DBG_ON) +#define debug(s, ...) printf("%s: " s "\n", "DHCP", ## __VA_ARGS__) +#else +#define debug(s, ...) +#endif /* Grow the size of the lwip dhcp_msg struct's options field, as LWIP defaults to a 68 octet options field for its DHCP client, and most full-sized clients send us more than this. */ #define DHCP_OPTIONS_LEN 312 -#include +#include +#include +#include _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 312, "dhcp_msg_t should have extended options size"); @@ -35,15 +45,20 @@ _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 3 typedef struct { uint8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + uint8_t active; uint32_t expires; } dhcp_lease_t; typedef struct { struct netconn *nc; uint8_t max_leases; - ip_addr_t first_client_addr; + ip4_addr_t first_client_addr; struct netif *server_if; dhcp_lease_t *leases; /* length max_leases */ + /* Optional router */ + ip4_addr_t router; + /* Optional DNS server */ + ip4_addr_t dns; } server_state_t; /* Only one DHCP server task can run at once, so we have global state @@ -68,39 +83,54 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr); /* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */ -inline static void sprintf_ipaddr(const ip_addr_t *addr, char *dest) +inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest) { - if(addr == NULL) + if (addr == NULL) sprintf(dest, "NULL"); else sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr), ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr)); } -void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases) +void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases) { /* Stop any existing running dhcpserver */ - if(dhcpserver_task_handle) + if (dhcpserver_task_handle) dhcpserver_stop(); state = malloc(sizeof(server_state_t)); state->max_leases = max_leases; state->leases = calloc(max_leases, sizeof(dhcp_lease_t)); + bzero(state->leases, max_leases * sizeof(dhcp_lease_t)); // state->server_if is assigned once the task is running - see comment in dhcpserver_task() - ip_addr_copy(state->first_client_addr, *first_client_addr); + ip4_addr_copy(state->first_client_addr, *first_client_addr); - xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle); + /* Clear options */ + ip4_addr_set_zero(&state->router); + ip4_addr_set_zero(&state->dns); + + xTaskCreate(dhcpserver_task, "DHCP Server", 448, NULL, 2, &dhcpserver_task_handle); } void dhcpserver_stop(void) { - if(dhcpserver_task_handle) { + if (dhcpserver_task_handle) { vTaskDelete(dhcpserver_task_handle); free(state); dhcpserver_task_handle = NULL; } } +void dhcpserver_set_router(const ip4_addr_t *router) +{ + ip4_addr_copy(state->router, *router); +} + +void dhcpserver_set_dns(const ip4_addr_t *dns) +{ + ip4_addr_copy(state->dns, *dns); +} + static void dhcpserver_task(void *pxParameter) { /* netif_list isn't assigned until after user_init completes, which is why we do it inside the task */ @@ -108,11 +138,12 @@ static void dhcpserver_task(void *pxParameter) state->nc = netconn_new (NETCONN_UDP); if(!state->nc) { - printf("DHCP Server Error: Failed to allocate socket.\r\n"); + debug("DHCP Server Error: Failed to allocate socket."); return; } - netconn_bind(state->nc, IP_ADDR_ANY, DHCP_SERVER_PORT); + netconn_bind(state->nc, IP4_ADDR_ANY, LWIP_IANA_PORT_DHCP_SERVER); + netconn_bind_if (state->nc, netif_get_index(state->server_if)); while(1) { @@ -122,29 +153,32 @@ static void dhcpserver_task(void *pxParameter) /* Receive a DHCP packet */ err_t err = netconn_recv(state->nc, &netbuf); if(err != ERR_OK) { - printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err); + debug("DHCP Server Error: Failed to receive DHCP packet. err=%d", err); continue; } /* expire any leases that have passed */ uint32_t now = xTaskGetTickCount(); - for(int i = 0; i < state->max_leases; i++) { - uint32_t expires = state->leases[i].expires; - if(expires && expires < now) - state->leases[i].expires = 0; + for (int i = 0; i < state->max_leases; i++) { + if (state->leases[i].active) { + uint32_t expires = state->leases[i].expires - now; + if (expires >= 0x80000000) { + state->leases[i].active = 0; + } + } } ip_addr_t received_ip; u16_t port; netconn_addr(state->nc, &received_ip, &port); - if(netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) { + if (netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) { /* too short to be a valid DHCP client message */ netbuf_delete(netbuf); continue; } if(netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) { - printf("DHCP Server Warning: Client sent more options than we know how to parse. len=%d\r\n", netbuf_len(netbuf)); + debug("DHCP Server Warning: Client sent more options than we know how to parse. len=%d", netbuf_len(netbuf)); } netbuf_copy(netbuf, &received, sizeof(struct dhcp_msg)); @@ -153,18 +187,19 @@ static void dhcpserver_task(void *pxParameter) uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE, DHCP_OPTION_MESSAGE_TYPE_LEN, NULL); if(!message_type) { - printf("DHCP Server Error: No message type field found"); + debug("DHCP Server Error: No message type field found"); continue; } - - printf("State dump. Message type %d\n", *message_type); +#if (DHCP_DEBUG == LWIP_DBG_ON) + debug("State dump. Message type %d", *message_type); for(int i = 0; i < state->max_leases; i++) { dhcp_lease_t *lease = &state->leases[i]; - printf("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, lease->expires, lease->hwaddr[0], + debug("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x", i, lease->expires, lease->hwaddr[0], lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[5]); } +#endif switch(*message_type) { case DHCP_DISCOVER: @@ -175,8 +210,9 @@ static void dhcpserver_task(void *pxParameter) break; case DHCP_RELEASE: handle_dhcp_release(&received); + break; default: - printf("DHCP Server Error: Unsupported message type %d\r\n", *message_type); + debug("DHCP Server Error: Unsupported message type %d", *message_type); break; } } @@ -184,14 +220,14 @@ static void dhcpserver_task(void *pxParameter) static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg) { - if(dhcpmsg->htype != DHCP_HTYPE_ETH) + if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET) return; - if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) + if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) return; dhcp_lease_t *freelease = find_lease_slot(dhcpmsg->chaddr); if(!freelease) { - printf("DHCP Server: All leases taken.\r\n"); + debug("DHCP Server: All leases taken."); return; /* Nothing available, so do nothing */ } @@ -199,13 +235,19 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg) dhcpmsg->op = DHCP_BOOTREPLY; bzero(dhcpmsg->options, DHCP_OPTIONS_LEN); - ip_addr_copy(dhcpmsg->yiaddr, state->first_client_addr); - ip4_addr4(&(dhcpmsg->yiaddr)) += (freelease - state->leases); + dhcpmsg->yiaddr.addr = lwip_htonl(lwip_ntohl(state->first_client_addr.addr) + (freelease - state->leases)); uint8_t *opt = (uint8_t *)&dhcpmsg->options; opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4); + if (!ip4_addr_isany_val(state->router)) { + opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4); + } + if (!ip4_addr_isany_val(state->dns)) { + opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4); + } + opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0); struct netbuf *netbuf = netbuf_new(); @@ -218,60 +260,64 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg) static void handle_dhcp_request(struct dhcp_msg *dhcpmsg) { static char ipbuf[16]; - if(dhcpmsg->htype != DHCP_HTYPE_ETH) + if (dhcpmsg->htype != LWIP_IANA_HWTYPE_ETHERNET) return; - if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) + if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN) return; - ip_addr_t requested_ip; + ip4_addr_t requested_ip; uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL); - if(requested_ip_opt) { - memcpy(&requested_ip.addr, requested_ip_opt, 4); - } else if(ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) { - ip_addr_copy(requested_ip, dhcpmsg->ciaddr); + if (requested_ip_opt) { + memcpy(&requested_ip.addr, requested_ip_opt, 4); + } else if (ip4_addr_cmp(&requested_ip, IP4_ADDR_ANY4)) { + ip4_addr_copy(requested_ip, dhcpmsg->ciaddr); } else { - printf("DHCP Server Error: No requested IP\r\n"); + debug("DHCP Server Error: No requested IP"); send_dhcp_nak(dhcpmsg); return; } /* Test the first 4 octets match */ - if(ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr) + if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr) || ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr) || ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) { sprintf_ipaddr(&requested_ip, ipbuf); - printf("DHCP Server Error: %s not an allowed IP\r\n", ipbuf); + debug("DHCP Server Error: %s not an allowed IP", ipbuf); send_dhcp_nak(dhcpmsg); return; } /* Test the last octet is in the MAXCLIENTS range */ int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr); if(octet_offs < 0 || octet_offs >= state->max_leases) { - printf("DHCP Server Error: Address out of range\r\n"); + debug("DHCP Server Error: Address out of range"); send_dhcp_nak(dhcpmsg); return; } dhcp_lease_t *requested_lease = state->leases + octet_offs; - if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen)) + if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen)) { - printf("DHCP Server Error: Lease for address already taken\r\n"); + debug("DHCP Server Error: Lease for address already taken"); send_dhcp_nak(dhcpmsg); return; } memcpy(requested_lease->hwaddr, dhcpmsg->chaddr, dhcpmsg->hlen); sprintf_ipaddr(&requested_ip, ipbuf); - printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0], + debug("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x", ipbuf, requested_lease->hwaddr[0], requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4], requested_lease->hwaddr[5]); - requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ; + uint32_t now = xTaskGetTickCount(); + requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ; + requested_lease->active = 1; + + sdk_wifi_softap_set_station_info(requested_lease->hwaddr, &requested_ip); /* Reuse the REQUEST message as the ACK message */ dhcpmsg->op = DHCP_BOOTREPLY; bzero(dhcpmsg->options, DHCP_OPTIONS_LEN); - ip_addr_copy(dhcpmsg->yiaddr, requested_ip); + ip4_addr_copy(dhcpmsg->yiaddr, requested_ip); uint8_t *opt = (uint8_t *)&dhcpmsg->options; opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_ACK); @@ -279,6 +325,13 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg) opt = add_dhcp_option_bytes(opt, DHCP_OPTION_LEASE_TIME, &expiry, 4); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SERVER_ID, &state->server_if->ip_addr, 4); opt = add_dhcp_option_bytes(opt, DHCP_OPTION_SUBNET_MASK, &state->server_if->netmask, 4); + if (!ip4_addr_isany_val(state->router)) { + opt = add_dhcp_option_bytes(opt, DHCP_OPTION_ROUTER, &state->router, 4); + } + if (!ip4_addr_isany_val(state->dns)) { + opt = add_dhcp_option_bytes(opt, DHCP_OPTION_DNS_SERVER, &state->dns, 4); + } + opt = add_dhcp_option_bytes(opt, DHCP_OPTION_END, NULL, 0); struct netbuf *netbuf = netbuf_new(); @@ -291,7 +344,8 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg) static void handle_dhcp_release(struct dhcp_msg *dhcpmsg) { dhcp_lease_t *lease = find_lease_slot(dhcpmsg->chaddr); - if(lease) { + if (lease) { + lease->active = 0; lease->expires = 0; } } @@ -319,17 +373,17 @@ static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8 uint8_t *start = (uint8_t *)&msg->options; uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg); - for(uint8_t *p = start; p < msg_end-2;) { + for (uint8_t *p = start; p < msg_end-2;) { uint8_t type = *p++; uint8_t len = *p++; - if(type == DHCP_OPTION_END) + if (type == DHCP_OPTION_END) return NULL; - if(p+len >= msg_end) + if (p+len >= msg_end) break; /* We've overrun our valid DHCP message size, or this isn't a valid option */ - if(type == option_num) { - if(len < min_length) + if (type == option_num) { + if (len < min_length) break; - if(length) + if (length) *length = len; return p; /* start of actual option data */ } @@ -349,7 +403,7 @@ static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value) static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len) { *opt++ = type; - if(len) { + if (len) { *opt++ = len; memcpy(opt, value, len); } @@ -360,8 +414,8 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr) { dhcp_lease_t *empty_lease = NULL; - for(int i = 0; i < state->max_leases; i++) { - if(state->leases[i].expires == 0 && !empty_lease) + for (int i = 0; i < state->max_leases; i++) { + if (!state->leases[i].active && !empty_lease) empty_lease = &state->leases[i]; else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0) return &state->leases[i]; diff --git a/extras/dhcpserver/include/dhcpserver.h b/extras/dhcpserver/include/dhcpserver.h index 95a59b8..62fa0ac 100644 --- a/extras/dhcpserver/include/dhcpserver.h +++ b/extras/dhcpserver/include/dhcpserver.h @@ -26,14 +26,20 @@ extern "C" { to a client. Subsequent lease addresses are calculated by incrementing the final octet of the IPv4 address, up to max_leases. */ -void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases); +void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases); -void dhcpserver_get_lease(const ip_addr_t *first_client_addr, uint8_t max_leases); +void dhcpserver_get_lease(const ip4_addr_t *first_client_addr, uint8_t max_leases); /* Stop DHCP server. */ void dhcpserver_stop(void); +/* Set a router address to send as an option. */ +void dhcpserver_set_router(const ip4_addr_t *router); + +/* Set a DNS address to send as an option. */ +void dhcpserver_set_dns(const ip4_addr_t *dns); + #ifdef __cplusplus } #endif diff --git a/extras/ds3231/ds3231.c b/extras/ds3231/ds3231.c index dfc5757..4b0e65c 100644 --- a/extras/ds3231/ds3231.c +++ b/extras/ds3231/ds3231.c @@ -15,13 +15,13 @@ /* Convert normal decimal to binary coded decimal */ static inline uint8_t decToBcd(uint8_t dec) { - return(((dec / 10) * 16) + (dec % 10)); + return (dec / 10) * 16 + dec % 10; } /* Convert binary coded decimal to normal decimal */ static inline uint8_t bcdToDec(uint8_t bcd) { - return(((bcd / 16) * 10) + (bcd % 16)); + return (bcd / 16) * 10 + bcd % 16; } /* Send a number of bytes to the rtc over i2c @@ -48,6 +48,8 @@ int ds3231_setTime(i2c_dev_t *dev, struct tm *time) data[0] = decToBcd(time->tm_sec); data[1] = decToBcd(time->tm_min); data[2] = decToBcd(time->tm_hour); + /* The week data must be in the range 1 to 7, and to keep the start on the + * same day as for tm_wday have it start at 1 on Sunday. */ data[3] = decToBcd(time->tm_wday + 1); data[4] = decToBcd(time->tm_mday); data[5] = decToBcd(time->tm_mon + 1); diff --git a/extras/httpd/httpd.c b/extras/httpd/httpd.c index f647ca6..fcbc290 100644 --- a/extras/httpd/httpd.c +++ b/extras/httpd/httpd.c @@ -139,7 +139,7 @@ /** Set this to 1 on platforms where strnstr is not available */ #ifndef LWIP_HTTPD_STRNSTR_PRIVATE -#define LWIP_HTTPD_STRNSTR_PRIVATE 1 +#define LWIP_HTTPD_STRNSTR_PRIVATE 0 #endif /** Set this to one to show error pages when parsing a request fails instead @@ -2675,7 +2675,7 @@ http_accept(void *arg, struct tcp_pcb *pcb, err_t err) * Initialize the httpd with the specified local address. */ static void -httpd_init_addr(ip_addr_t *local_addr) +httpd_init_addr(const ip_addr_t *local_addr) { struct tcp_pcb *pcb; err_t err; diff --git a/extras/i2c/README.md b/extras/i2c/README.md index cac119d..d36209b 100644 --- a/extras/i2c/README.md +++ b/extras/i2c/README.md @@ -2,11 +2,12 @@ This time a driver for the excellent esp-open-rtos. This is a bit banging I2C driver based on the Wikipedia pesudo C code [1]. -### Usage +### Basic usage -```` +```C #include +#define BUS (0) #define SCL_PIN (0) #define SDA_PIN (2) @@ -14,19 +15,19 @@ uint8_t slave_addr = 0x20; uint8_t reg_addr = 0x1f; uint8_t reg_data; -i2c_init(SCL_PIN, SDA_PIN); +i2c_init(BUS, SCL_PIN, SDA_PIN, I2C_FREQ_400K); // Write 1 byte to slave register -int err = i2c_slave_write(slave_addr, ®_addr, &data, 1); +int err = i2c_slave_write(BUS, slave_addr, ®_addr, &data, 1); if (err != 0) { // do something with error } // Issue write to slave, sending reg_addr, followed by reading 1 byte -err = i2c_slave_read(slave_addr, ®_addr, ®_data, 1); +err = i2c_slave_read(BUS, slave_addr, ®_addr, ®_data, 1); -```` +``` For details please see `extras/i2c/i2c.h`. diff --git a/extras/i2c/i2c.c b/extras/i2c/i2c.c index 034bcdc..3ba0caf 100644 --- a/extras/i2c/i2c.c +++ b/extras/i2c/i2c.c @@ -22,10 +22,13 @@ * THE SOFTWARE. */ +#include "i2c.h" + #include #include // sdk_os_delay_us #include -#include "i2c.h" +#include +#include //#define I2C_DEBUG true @@ -37,7 +40,28 @@ #define CLK_STRETCH (10) -static uint8_t freq ; // Store CPU frequency for optimisation speed in delay function ( Warning: Don't change CPU frequency during a transaction) +// Following array contain delay values for different frequencies +// Warning: 1 is minimal, that mean at 80MHz clock, frequency max is 320kHz +const static uint8_t i2c_freq_array[][2] = { + [I2C_FREQ_80K] = {255, 35}, + [I2C_FREQ_100K] = {100, 20}, + [I2C_FREQ_400K] = {10, 1}, + [I2C_FREQ_500K] = {6, 1} +}; + +static uint8_t freq; // Store CPU frequency for optimisation speed in delay function (Warning: Don't change CPU frequency during a transaction) + +// Bus settings +typedef struct i2c_bus_description +{ + uint8_t g_scl_pin; // SCL pin + uint8_t g_sda_pin; // SDA pin + i2c_freq_t frequency; // Frequency + bool started; + bool flag; + bool force; +} i2c_bus_description_t; + static i2c_bus_description_t i2c_bus[MAX_I2C_BUS]; inline bool i2c_status(uint8_t bus) @@ -48,10 +72,10 @@ inline bool i2c_status(uint8_t bus) void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq) { i2c_bus[bus].started = false; - i2c_bus[bus].flag = false ; + i2c_bus[bus].flag = false; i2c_bus[bus].g_scl_pin = scl_pin; i2c_bus[bus].g_sda_pin = sda_pin; - i2c_bus[bus].frequency = freq ; + i2c_bus[bus].frequency = freq; // Just to prevent these pins floating too much if not connected. gpio_set_pullup(i2c_bus[bus].g_scl_pin, 1, 1); @@ -73,7 +97,7 @@ void i2c_init(uint8_t bus, uint8_t scl_pin, uint8_t sda_pin, i2c_freq_t freq) void i2c_frequency(uint8_t bus, i2c_freq_t freq) { - i2c_bus[bus].frequency = freq ; + i2c_bus[bus].frequency = freq; } static inline void i2c_delay(uint8_t bus) @@ -136,13 +160,14 @@ void i2c_start(uint8_t bus) (void) read_sda(bus); i2c_delay(bus); uint32_t clk_stretch = CLK_STRETCH; - while (read_scl(bus) == 0 && clk_stretch--) ; + while (read_scl(bus) == 0 && clk_stretch--) + ; // Repeated start setup time, minimum 4.7us i2c_delay(bus); } i2c_bus[bus].started = true; if (read_sda(bus) == 0) { - debug("arbitration lost in i2c_start from bus %u",bus); + debug("arbitration lost in i2c_start from bus %u", bus); } // SCL is high, set SDA from 1 to 0. clear_sda(bus); @@ -158,17 +183,18 @@ bool i2c_stop(uint8_t bus) clear_sda(bus); i2c_delay(bus); // Clock stretching - while (read_scl(bus) == 0 && clk_stretch--) ; + while (read_scl(bus) == 0 && clk_stretch--) + ; // Stop bit setup time, minimum 4us i2c_delay(bus); // SCL is high, set SDA from 0 to 1 if (read_sda(bus) == 0) { - debug("arbitration lost in i2c_stop from bus %u",bus); + debug("arbitration lost in i2c_stop from bus %u", bus); } i2c_delay(bus); if (!i2c_bus[bus].started) { - debug("bus %u link was break!",bus); - return false ; //If bus was stop in other way, the current transmission Failed + debug("bus %u link was break!", bus); + return false; // If bus was stop in other way, the current transmission Failed } i2c_bus[bus].started = false; return true; @@ -185,11 +211,12 @@ static void i2c_write_bit(uint8_t bus, bool bit) } i2c_delay(bus); // Clock stretching - while (read_scl(bus) == 0 && clk_stretch--) ; + while (read_scl(bus) == 0 && clk_stretch--) + ; // SCL is high, now data is valid // If SDA is high, check that nobody else is driving SDA if (bit && read_sda(bus) == 0) { - debug("arbitration lost in i2c_write_bit from bus %u",bus); + debug("arbitration lost in i2c_write_bit from bus %u", bus); } i2c_delay(bus); clear_scl(bus); @@ -204,7 +231,8 @@ static bool i2c_read_bit(uint8_t bus) (void) read_sda(bus); i2c_delay(bus); // Clock stretching - while (read_scl(bus) == 0 && clk_stretch--) ; + while (read_scl(bus) == 0 && clk_stretch--) + ; // SCL is high, now data is valid bit = read_sda(bus); i2c_delay(bus); @@ -217,7 +245,7 @@ bool i2c_write(uint8_t bus, uint8_t byte) bool nack; uint8_t bit; for (bit = 0; bit < 8; bit++) { - i2c_write_bit(bus,(byte & 0x80) != 0); + i2c_write_bit(bus, (byte & 0x80) != 0); byte <<= 1; } nack = i2c_read_bit(bus); @@ -231,22 +259,22 @@ uint8_t i2c_read(uint8_t bus, bool ack) for (bit = 0; bit < 8; bit++) { byte = ((byte << 1)) | (i2c_read_bit(bus)); } - i2c_write_bit(bus,ack); + i2c_write_bit(bus, ack); return byte; } void i2c_force_bus(uint8_t bus, bool state) { - i2c_bus[bus].force = state ; + i2c_bus[bus].force = state; } static int i2c_bus_test(uint8_t bus) { taskENTER_CRITICAL(); // To prevent task swaping after checking flag and before set it! - bool status = i2c_bus[bus].flag ; // get current status + bool status = i2c_bus[bus].flag; // get current status if(i2c_bus[bus].force) { - i2c_bus[bus].flag = true ; // force bus on + i2c_bus[bus].flag = true; // force bus on taskEXIT_CRITICAL(); if(status) i2c_stop(bus); //Bus was busy, stop it. @@ -258,72 +286,72 @@ static int i2c_bus_test(uint8_t bus) taskEXIT_CRITICAL(); debug("busy"); taskYIELD(); // If bus busy, change task to try finish last com. - return -EBUSY ; // If bus busy, inform user + return -EBUSY; // If bus busy, inform user } else { - i2c_bus[bus].flag = true ; // Set Bus busy + i2c_bus[bus].flag = true; // Set Bus busy taskEXIT_CRITICAL(); } } - return 0 ; + return 0; } int i2c_slave_write(uint8_t bus, uint8_t slave_addr, const uint8_t *data, const uint8_t *buf, uint32_t len) { if(i2c_bus_test(bus)) - return -EBUSY ; + return -EBUSY; i2c_start(bus); if (!i2c_write(bus, slave_addr << 1)) goto error; if(data != NULL) - if (!i2c_write(bus,*data)) + if (!i2c_write(bus, *data)) goto error; while (len--) { - if (!i2c_write(bus,*buf++)) + if (!i2c_write(bus, *buf++)) goto error; } if (!i2c_stop(bus)) goto error; - i2c_bus[bus].flag = false ; // Bus free + i2c_bus[bus].flag = false; // Bus free return 0; - error: - debug("Bus %u Write Error",bus); +error: + debug("Bus %u Write Error", bus); i2c_stop(bus); - i2c_bus[bus].flag = false ; // Bus free + i2c_bus[bus].flag = false; // Bus free return -EIO; } int i2c_slave_read(uint8_t bus, uint8_t slave_addr, const uint8_t *data, uint8_t *buf, uint32_t len) { if(i2c_bus_test(bus)) - return -EBUSY ; + return -EBUSY; if(data != NULL) { i2c_start(bus); - if (!i2c_write(bus,slave_addr << 1)) + if (!i2c_write(bus, slave_addr << 1)) goto error; - if (!i2c_write(bus,*data)) + if (!i2c_write(bus, *data)) goto error; if (!i2c_stop(bus)) goto error; } i2c_start(bus); - if (!i2c_write(bus,slave_addr << 1 | 1)) // Slave address + read + if (!i2c_write(bus, slave_addr << 1 | 1)) // Slave address + read goto error; while(len) { - *buf = i2c_read(bus,len == 1); + *buf = i2c_read(bus, len == 1); buf++; len--; } if (!i2c_stop(bus)) goto error; - i2c_bus[bus].flag = false ; // Bus free + i2c_bus[bus].flag = false; // Bus free return 0; - error: +error: debug("Read Error"); i2c_stop(bus); - i2c_bus[bus].flag = false ; // Bus free + i2c_bus[bus].flag = false; // Bus free return -EIO; } diff --git a/extras/i2c/i2c.h b/extras/i2c/i2c.h index c2e31cd..80015a6 100644 --- a/extras/i2c/i2c.h +++ b/extras/i2c/i2c.h @@ -21,6 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * I2C driver for ESP8266 written for use with esp-open-rtos + * Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol + */ #ifndef __I2C_H__ #define __I2C_H__ @@ -28,62 +32,36 @@ #include #include #include -#include -#include #ifdef __cplusplus extern "C" { #endif - -/* - * Define i2c bus max number +/** + * Define i2c bus max number */ -#define MAX_I2C_BUS 2 +#ifndef MAX_I2C_BUS + #define MAX_I2C_BUS 2 +#endif - -/* - * following array contain value for different frequency - * Warning : 1 is minimal, that mean at 80MHz clock, frequency max is 320kHz - * Array format is { {160MHz, 80MHz} , {160MHz, 80MHz} , ... } - */ -#define NB_FREQ_AVAILABLE 4 - - typedef enum { - I2C_FREQ_80K = 0, - I2C_FREQ_100K, - I2C_FREQ_400K, - I2C_FREQ_500K, +typedef enum +{ + I2C_FREQ_80K = 0,//!< I2C_FREQ_80K + I2C_FREQ_100K, //!< I2C_FREQ_100K + I2C_FREQ_400K, //!< I2C_FREQ_400K + I2C_FREQ_500K, //!< I2C_FREQ_500K } i2c_freq_t; -const static uint8_t i2c_freq_array[NB_FREQ_AVAILABLE][2] = { {255,35}, {100,20}, {10,1}, {6,1} } ; - /** * Device descriptor */ -typedef struct i2c_dev { - uint8_t bus ; - uint8_t addr ; -} i2c_dev_t ; +typedef struct i2c_dev +{ + uint8_t bus; + uint8_t addr; +} i2c_dev_t; -/** - * Bus settings - */ -typedef struct i2c_bus_description { - uint8_t g_scl_pin; // Scl pin - uint8_t g_sda_pin; // Sda pin - uint8_t frequency; // frequency selection - bool started; - bool flag; - bool force; -} i2c_bus_description_t ; - - -// I2C driver for ESP8266 written for use with esp-open-rtos -// Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol -// With calling overhead, we end up at ~320kbit/s - -//Level 0 API +/// Level 0 API /** * Init bitbanging I2C driver on given pins @@ -137,7 +115,7 @@ bool i2c_stop(uint8_t bus); */ bool i2c_status(uint8_t bus); -//Level 1 API (Don't need functions above) +/// Level 1 API (Don't need functions above) /** * This function will allow you to force a transmission I2C, cancel current transmission. diff --git a/extras/i2s_dma/i2s_dma.c b/extras/i2s_dma/i2s_dma.c index 442cdf3..9609f1b 100644 --- a/extras/i2s_dma/i2s_dma.c +++ b/extras/i2s_dma/i2s_dma.c @@ -62,7 +62,7 @@ void sdk_rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id, reg_add##_lsb, indata) -void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins) +void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins) { // reset DMA SET_MASK_BITS(SLC.CONF0, SLC_CONF0_RX_LINK_RESET); @@ -83,7 +83,7 @@ void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins) SLC_RX_DESCRIPTOR_CONF_RX_EOF_MODE | SLC_RX_DESCRIPTOR_CONF_RX_FILL_MODE); if (isr) { - _xt_isr_attach(INUM_SLC, isr); + _xt_isr_attach(INUM_SLC, isr, arg); SET_MASK_BITS(SLC.INT_ENABLE, SLC_INT_ENABLE_RX_EOF); SLC.INT_CLEAR = 0xFFFFFFFF; _xt_isr_unmask(1<= 1 /* save server address to verify it in sntp_recv */ ip_addr_set(&sntp_last_server_address, server_addr); @@ -629,7 +629,7 @@ sntp_send_request(ip_addr_t *server_addr) * DNS found callback when using DNS names as server address. */ static void -sntp_dns_found(const char* hostname, ip_addr_t *ipaddr, void *arg) +sntp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) { LWIP_UNUSED_ARG(hostname); LWIP_UNUSED_ARG(arg); diff --git a/extras/sntp/sntp_fun.c b/extras/sntp/sntp_fun.c index 7aaca20..96e8ffc 100644 --- a/extras/sntp/sntp_fun.c +++ b/extras/sntp/sntp_fun.c @@ -102,7 +102,7 @@ void sntp_update_rtc(time_t t, uint32_t us) { // DEBUG: Compute and print drift int64_t sntp_current = sntp_base + TIMER_COUNT - tim_ref; int64_t sntp_correct = (((uint64_t)us + (uint64_t)t * 1000000U)<<12) / cal; - printf("\nRTC Adjust: drift = %ld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), cal); + printf("\nRTC Adjust: drift = %lld ticks, cal = %d\n", (time_t)(sntp_correct - sntp_current), (uint32_t)cal); tim_ref = TIMER_COUNT; cal = sdk_system_rtc_clock_cali_proc(); diff --git a/extras/stdin_uart_interrupt/stdin_uart_interrupt.c b/extras/stdin_uart_interrupt/stdin_uart_interrupt.c index 3319588..194fdda 100644 --- a/extras/stdin_uart_interrupt/stdin_uart_interrupt.c +++ b/extras/stdin_uart_interrupt/stdin_uart_interrupt.c @@ -44,7 +44,7 @@ static SemaphoreHandle_t uart0_sem = NULL; static bool inited = false; static void uart0_rx_init(void); -IRAM void uart0_rx_handler(void) +IRAM void uart0_rx_handler(void *arg) { // TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) { @@ -97,7 +97,7 @@ static void uart0_rx_init(void) int trig_lvl = 1; uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0); - _xt_isr_attach(INUM_UART, uart0_rx_handler); + _xt_isr_attach(INUM_UART, uart0_rx_handler, NULL); _xt_isr_unmask(1 << INUM_UART); // reset the rx fifo diff --git a/extras/wificfg/component.mk b/extras/wificfg/component.mk new file mode 100644 index 0000000..5412c52 --- /dev/null +++ b/extras/wificfg/component.mk @@ -0,0 +1,10 @@ +# Component makefile for extras/wificfg + +# Expected anyone using wificfg includes it as 'wificfg/wificfg.h' +INC_DIRS += $(wificfg_ROOT).. + +# args for passing into compile rule generation +wificfg_INC_DIR = +wificfg_SRC_DIR = $(wificfg_ROOT) + +$(eval $(call component_compile_rules,wificfg)) diff --git a/extras/wificfg/content/challenge.html b/extras/wificfg/content/challenge.html new file mode 100644 index 0000000..568ead2 --- /dev/null +++ b/extras/wificfg/content/challenge.html @@ -0,0 +1,30 @@ +"" +"" +"" +"" +"", +"" +"" +"" +"" +"" +"
" +"
" +"Unlock the configuration interface" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"" diff --git a/extras/wificfg/content/favicon.ico b/extras/wificfg/content/favicon.ico new file mode 100644 index 0000000..93f7af2 --- /dev/null +++ b/extras/wificfg/content/favicon.ico @@ -0,0 +1,11 @@ +"HTTP/1.1 200 \r\n" +"Content-Type: image/svg+xml\r\n" +"Cache-Control: max-age=900\r\n" +"Transfer-Encoding: chunked\r\n" +"Connection: close\r\n" +"\r\n", +"" +"" +"" +"" +"" diff --git a/extras/wificfg/content/script.js b/extras/wificfg/content/script.js new file mode 100644 index 0000000..68064c5 --- /dev/null +++ b/extras/wificfg/content/script.js @@ -0,0 +1,8 @@ +"HTTP/1.1 200 \r\n" +"Content-Type: text/javascript\r\n" +"Cache-Control: max-age=900\r\n" +"Transfer-Encoding: chunked\r\n" +"Connection: close\r\n" +"\r\n", +"function myFunction() { var x = document.getElementById(\"myTopnav\");" +"if (x.className === \"topnav\") { x.className += \" responsive\"; } else { x.className = \"topnav\"; } }" diff --git a/extras/wificfg/content/style.css b/extras/wificfg/content/style.css new file mode 100644 index 0000000..9155940 --- /dev/null +++ b/extras/wificfg/content/style.css @@ -0,0 +1,19 @@ +"HTTP/1.1 200 \r\n" +"Content-Type: text/css\r\n" +"Cache-Control: max-age=900\r\n" +"Transfer-Encoding: chunked\r\n" +"\r\n", +".dlh dd,h1{font-weight:300}.dlh{font-size:0;text-align:center}" +".dlh dd,.dlh dt{width:48%;width:calc(50% - 10px);margin:8px 0;display:inline-block;font-size:16px;vertical-align:middle}" +".dlh dt{text-align:right;padding-right:10px}" +".dlh dd{font-size:18px;text-align:left;padding-left:10px}" +"ul.topnav{list-style-type:none;margin:0;padding:0;overflow:hidden;background-color:#bbb}" +"ul.topnav li{float:left}" +"ul.topnav li a{display:inline-block;color:#444;text-align:center;padding:14px 16px;text-decoration:none;transition:.3s;font-size:17px}" +"ul.topnav li a:hover{background-color:#ddd}ul.topnav li.icon{display:none}" +"@media screen and (max-width:680px){ul.topnav li:not(.active){display:none}ul.topnav li.icon{float:right;display:inline-block}ul.topnav.responsive{position:relative}ul.topnav.responsive li.icon{position:absolute;right:0;top:0}ul.topnav.responsive li{float:none;display:inline}ul.topnav.responsive li a{display:block;text-align:left}}" +"html{min-height:100%}" +"body{background:#d0e4f7;background:-moz-linear-gradient(top, #d0e4f7 0%, #73b1e7 24%, #0a77d5 50%, #539fe1 79%, #87bcea 100%);background:-webkit-linear-gradient(top, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);background:linear-gradient(to bottom, #d0e4f7 0%,#73b1e7 24%,#0a77d5 50%,#539fe1 79%,#87bcea 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d0e4f7', endColorstr='#87bcea',GradientType=0)}" +"body{font-family:helvetica,arial,sans-serif;font-size:16px}" +"h1{font-size:26px}" +"p{font-size:14px}" diff --git a/extras/wificfg/content/tasks.html b/extras/wificfg/content/tasks.html new file mode 100644 index 0000000..d084ea7 --- /dev/null +++ b/extras/wificfg/content/tasks.html @@ -0,0 +1,18 @@ +"" +"" +"" +"" +"", +"" +"" +"" +"" +"", +"" diff --git a/extras/wificfg/content/wificfg/ap.html b/extras/wificfg/content/wificfg/ap.html new file mode 100644 index 0000000..8dbb730 --- /dev/null +++ b/extras/wificfg/content/wificfg/ap.html @@ -0,0 +1,90 @@ +"" +"" +"" +"" +"", +"" +"" +"" +"" +"" +"
" +"
" +"WiFi Access Point configuration" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
 
" +"
" +"" +"
" +"" diff --git a/extras/wificfg/content/wificfg/index.html b/extras/wificfg/content/wificfg/index.html new file mode 100644 index 0000000..cb81712 --- /dev/null +++ b/extras/wificfg/content/wificfg/index.html @@ -0,0 +1,52 @@ +"" +"" +"" +"" +"", +"" +"" +"" +"" +"" +"

WiFi Status

" +"
", +"
" +"
" +"
" +"
" +"Lock the configuration interface" +"

These WiFi configuration pages can be disabled for security on a shared network. If a password is supplied then they can be unlocked. Warning: if no password is supplied then it will not be possible to unlock these pages via this interface.

" +"
" +"
" +"
" +"
" +"" +"
" +"
" +"
" +"
" +"
" +"Restart device" +"

A restart is necessary for some changes to take effect.

" +"
" +"
" +"
" +"
" +"Erase configuration" +"

Erases the device configuration stored in the flash memory and restarts the device. " +"This might be useful to clear stored passwords and private configuration information." +"

" +"
" +"
" +"
", +"" diff --git a/extras/wificfg/content/wificfg/sta.html b/extras/wificfg/content/wificfg/sta.html new file mode 100644 index 0000000..65bfe9d --- /dev/null +++ b/extras/wificfg/content/wificfg/sta.html @@ -0,0 +1,68 @@ +"" +"" +"" +"" +"", +"" +"" +"" +"" +"" +"
" +"
" +"WiFi Station configuration" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
" +"
 
" +"
" +"" +"
" +"" diff --git a/extras/wificfg/wificfg.c b/extras/wificfg/wificfg.c new file mode 100644 index 0000000..708af29 --- /dev/null +++ b/extras/wificfg/wificfg.c @@ -0,0 +1,2022 @@ +/* + * WiFi configuration via a simple web server. + * + * Copyright (C) 2016 OurAirQuality.org + * + * Licensed under the Apache License, Version 2.0, January 2004 (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/ + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS WITH THE SOFTWARE. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" + +#include "wificfg.h" +#include "sysparam.h" + +char *wificfg_default_ssid = "EOR_%02X%02X%02X"; +char *wificfg_default_password = "esp-open-rtos"; +char *wificfg_default_hostname = "eor-%02x%02x%02x"; + +/* The http task stack allocates a single buffer to do much of it's work. */ +#define HTTP_BUFFER_SIZE 54 + +/* + * Read a line terminated by "\r\n" or "\n" to be robust. Used to read the http + * status line and headers. On success returns the number of characters read, + * which might be more that the available buffer size 'len'. Excess characters + * in a line are discarded as a protection against excessively long lines. On + * failure -1 is returned. The character case is lowered to give a canonical + * case for easier comparision. The buffer is null terminated on success, even + * if truncated. + */ +static int read_crlf_line(int s, char *buf, size_t len) +{ + size_t num = 0; + + do { + char c; + int r = read(s, &c, 1); + + /* Expecting a known terminator so fail on EOF. */ + if (r <= 0) + return -1; + + if (c == '\n') + break; + + /* Remove a trailing '\r', and many unexpected characters. */ + if (c < 0x20 || c > 0x7e) + continue; + + if (num < len) + buf[num] = tolower((unsigned char)c); + + num++; + } while(1); + + /* Null terminate. */ + buf[num >= len ? len - 1 : num] = 0; + + return num; +} + +int wificfg_form_name_value(int s, bool *valp, size_t *rem, char *buf, size_t len) +{ + size_t num = 0; + + do { + if (*rem == 0) + break; + + char c; + int r = read(s, &c, 1); + + /* Expecting a known number of characters so fail on EOF. */ + if (r <= 0) return -1; + + (*rem)--; + + if (valp && c == '=') { + *valp = true; + break; + } + + if (c == '&') { + if (valp) + *valp = false; + break; + } + + if (num < len) + buf[num] = c; + + num++; + } while(1); + + /* Null terminate. */ + buf[num >= len ? len - 1 : num] = 0; + + return num; +} + +void wificfg_form_url_decode(char *string) +{ + char *src = string; + char *src_end = string + strlen(string); + char *dst = string; + + while (src < src_end) { + char c = *src++; + if (c == '+') { + c = ' '; + } else if (c == '%' && src < src_end - 1) { + unsigned char c1 = src[0]; + unsigned char c2 = src[1]; + if (isxdigit(c1) && isxdigit(c2)) { + c1 = tolower(c1); + int d1 = (c1 >= 'a' && c1 <= 'z') ? c1 - 'a' + 10 : c1 - '0'; + c2 = tolower(c2); + int d2 = (c2 >= 'a' && c2 <= 'z') ? c2 - 'a' + 10 : c2 - '0'; + *dst++ = (d1 << 4) + d2; + src += 2; + continue; + } + } + *dst++ = c; + } + + *dst = 0; +} + +/* HTML escaping. */ +void wificfg_html_escape(char *string, char *buf, size_t len) +{ + size_t i; + size_t out = 0; + + for (i = 0, out = 0; out < len - 1; ) { + char c = string[i++]; + if (!c) + break; + + if (c == '&') { + if (out >= len - 5) + break; + buf[out] = '&'; + buf[out + 1] = 'a'; + buf[out + 2] = 'm'; + buf[out + 3] = 'p'; + buf[out + 4] = ';'; + out += 5; + continue; + } + if (c == '"') { + if (out >= len - 6) + break; + buf[out] = '&'; + buf[out + 1] = 'q'; + buf[out + 2] = 'u'; + buf[out + 3] = 'o'; + buf[out + 4] = 't'; + buf[out + 5] = ';'; + out += 6; + continue; + } + if (c == '<') { + if (out >= len - 4) + break; + buf[out] = '&'; + buf[out + 1] = 'l'; + buf[out + 2] = 't'; + buf[out + 3] = ';'; + out += 4; + continue; + } + if (c == '>') { + if (out >= len - 4) + break; + buf[out] = '&'; + buf[out + 1] = 'g'; + buf[out + 2] = 't'; + buf[out + 3] = ';'; + out += 4; + continue; + } + + buf[out++] = c; + } + + buf[out] = 0; +} + +/* Various keywords are interned as they are read. */ + +static const struct { + const char *str; + wificfg_method method; +} method_table[] = { + {"get", HTTP_METHOD_GET}, + {"post", HTTP_METHOD_POST}, + {"head", HTTP_METHOD_HEAD} +}; + +static wificfg_method intern_http_method(char *str) +{ + int i; + for (i = 0; i < sizeof(method_table) / sizeof(method_table[0]); i++) { + if (!strcmp(str, method_table[i].str)) + return method_table[i].method; + } + return HTTP_METHOD_OTHER; +} + +/* + * The web server recognizes only these header names. Other headers are ignored. + */ +typedef enum { + HTTP_HEADER_HOST, + HTTP_HEADER_CONTENT_LENGTH, + HTTP_HEADER_CONTENT_TYPE, + HTTP_HEADER_CONNECTION, + HTTP_HEADER_OTHER +} http_header; + +static const struct { + const char *str; + http_header name; +} http_header_table[] = { + {"host", HTTP_HEADER_HOST}, + {"content-length", HTTP_HEADER_CONTENT_LENGTH}, + {"content-type", HTTP_HEADER_CONTENT_TYPE}, + {"connection", HTTP_HEADER_CONNECTION} +}; + +static http_header intern_http_header(char *str) +{ + int i; + for (i = 0; i < sizeof(http_header_table) / sizeof(http_header_table[0]); i++) { + if (!strcmp(str, http_header_table[i].str)) + return http_header_table[i].name; + } + return HTTP_HEADER_OTHER; +} + + +static const struct { + const char *str; + wificfg_content_type type; +} content_type_table[] = { + {"application/x-www-form-urlencoded", HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED} +}; + +static wificfg_content_type intern_http_content_type(char *str) +{ + int i; + for (i = 0; i < sizeof(content_type_table) / sizeof(content_type_table[0]); i++) { + if (!strcmp(str, content_type_table[i].str)) + return content_type_table[i].type; + } + return HTTP_CONTENT_TYPE_OTHER; +} + +static char *skip_whitespace(char *string) +{ + while (isspace((unsigned char)*string)) string++; + return string; +} + +static char *skip_to_whitespace(char *string) +{ + do { + unsigned char c = *string; + if (!c || isspace(c)) + break; + string++; + } while (1); + + return string; +} + +int wificfg_write_string(int s, const char *str) +{ + int res = write(s, str, strlen(str)); + return res; +} + +int wificfg_write_string_chunk(int s, const char *str, char *buf, size_t len) +{ + size_t str_len = strlen(str); + + if (str_len == 0) { + /* Can not be encoded, would be EOF. */ + return 0; + } + + if (str_len + 6 < len) { + /* Can fit the chunk in the buffer. */ + memmove(buf + 4, str, str_len); + size_t start = 1; + if (str_len < 10) { + buf[1] = '0' + str_len; + } else if (str_len < 16) { + buf[1] = 'a' + str_len - 10; + } else { + uint32_t digit0 = str_len >> 4; + if (digit0 < 10) { + buf[0] = '0' + digit0; + } else { + buf[0] = 'a' + digit0 - 10; + } + uint32_t digit1 = str_len & 0xf; + if (digit1 < 10) { + buf[1] = '0' + digit1; + } else { + buf[1] = 'a' + digit1 - 10; + } + start = 0; + } + buf[2] = '\r'; + buf[3] = '\n'; + buf[4 + str_len] = '\r'; + buf[4 + str_len + 1] = '\n'; + return write(s, buf + start, 4 - start + str_len + 2); + } + + /* Else too big for the buffer. */ + char size_buf[8]; + size_t size_len = snprintf(size_buf, sizeof(size_buf), "%x\r\n", str_len); + int res = write(s, size_buf, size_len); + if (res != size_len) { + return res; + } + res = write(s, str, str_len); + if (res != str_len) { + return res; + } + return write(s, size_buf + size_len - 2, 2); +} + +int wificfg_write_chunk_end(int s) +{ + return wificfg_write_string(s, "0\r\n\r\n"); +} + +typedef enum { + FORM_NAME_CFG_ENABLE, + FORM_NAME_CFG_PASSWORD, + FORM_NAME_HOSTNAME, + FORM_NAME_STA_ENABLE, + FORM_NAME_STA_DISABLED_RESTARTS, + FORM_NAME_STA_SSID, + FORM_NAME_STA_PASSWORD, + FORM_NAME_STA_DHCP, + FORM_NAME_STA_IP_ADDR, + FORM_NAME_STA_NETMASK, + FORM_NAME_STA_GATEWAY, + FORM_NAME_AP_ENABLE, + FORM_NAME_AP_DISABLE_IF_STA, + FORM_NAME_AP_DISABLED_RESTARTS, + FORM_NAME_AP_SSID, + FORM_NAME_AP_PASSWORD, + FORM_NAME_AP_SSID_HIDDEN, + FORM_NAME_AP_CHANNEL, + FORM_NAME_AP_AUTHMODE, + FORM_NAME_AP_MAX_CONN, + FORM_NAME_AP_BEACON_INTERVAL, + FORM_NAME_AP_IP_ADDR, + FORM_NAME_AP_NETMASK, + FORM_NAME_AP_DHCP_LEASES, + FORM_NAME_AP_DNS, + FORM_NAME_DONE, + FORM_NAME_NONE +} form_name; + +static const struct { + const char *str; + form_name name; +} form_name_table[] = { + {"cfg_enable", FORM_NAME_CFG_ENABLE}, + {"cfg_password", FORM_NAME_CFG_PASSWORD}, + {"hostname", FORM_NAME_HOSTNAME}, + {"sta_enable", FORM_NAME_STA_ENABLE}, + {"sta_disabled_restarts", FORM_NAME_STA_DISABLED_RESTARTS}, + {"sta_ssid", FORM_NAME_STA_SSID}, + {"sta_dhcp", FORM_NAME_STA_DHCP}, + {"sta_password", FORM_NAME_STA_PASSWORD}, + {"sta_ip_addr", FORM_NAME_STA_IP_ADDR}, + {"sta_netmask", FORM_NAME_STA_NETMASK}, + {"sta_gateway", FORM_NAME_STA_GATEWAY}, + {"ap_enable", FORM_NAME_AP_ENABLE}, + {"ap_disable_if_sta", FORM_NAME_AP_DISABLE_IF_STA}, + {"ap_disabled_restarts", FORM_NAME_AP_DISABLED_RESTARTS}, + {"ap_ssid", FORM_NAME_AP_SSID}, + {"ap_password", FORM_NAME_AP_PASSWORD}, + {"ap_ssid_hidden", FORM_NAME_AP_SSID_HIDDEN}, + {"ap_channel", FORM_NAME_AP_CHANNEL}, + {"ap_authmode", FORM_NAME_AP_AUTHMODE}, + {"ap_max_conn", FORM_NAME_AP_MAX_CONN}, + {"ap_beacon_interval", FORM_NAME_AP_BEACON_INTERVAL}, + {"ap_ip_addr", FORM_NAME_AP_IP_ADDR}, + {"ap_netmask", FORM_NAME_AP_NETMASK}, + {"ap_dhcp_leases", FORM_NAME_AP_DHCP_LEASES}, + {"ap_dns", FORM_NAME_AP_DNS}, + {"done", FORM_NAME_DONE} +}; + +static form_name intern_form_name(char *str) +{ + int i; + for (i = 0; i < sizeof(form_name_table) / sizeof(form_name_table[0]); i++) { + if (!strcmp(str, form_name_table[i].str)) + return form_name_table[i].name; + } + return FORM_NAME_NONE; +} + + +static const char *http_favicon[] = { +#include "content/favicon.ico" +}; + +static int handle_favicon(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_favicon[0]) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_favicon[1], buf, len) < 0) return -1; + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +// .value-lg{font-size:24px}.label-extra{display:block;font-style:italic;font-size:13px} +// devo: "Cache-Control: no-store\r\n" +static const char *http_style[] = { +#include "content/style.css" +}; + + +static int handle_style(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_style[0]) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_style[1], buf, len) < 0) return -1; + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +static const char *http_script[] = { +#include "content/script.js" +}; + +static int handle_script(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_script[0]) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_script[1], buf, len) < 0) return -1; + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + + +static const char http_success_header[] = "HTTP/1.1 200 \r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Cache-Control: no-store\r\n" + "Transfer-Encoding: chunked\r\n" + "Connection: close\r\n" + "\r\n"; + +static const char http_redirect_header[] = "HTTP/1.1 302 \r\n" + "Location: /wificfg/\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n" + "\r\n"; + +static int handle_wificfg_redirect(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + return wificfg_write_string(s, http_redirect_header); +} + +static int handle_ipaddr_redirect(int s, char *buf, size_t len) +{ + if (wificfg_write_string(s, "HTTP/1.1 302 \r\nLocation: http://") < 0) return -1; + + struct sockaddr addr; + socklen_t addr_len = sizeof(addr); + getsockname(s, &addr, &addr_len); + struct sockaddr_in *sa = (struct sockaddr_in *)&addr; + snprintf(buf, len, "" IPSTR "/\r\n", IP2STR((ip4_addr_t *)&sa->sin_addr.s_addr)); + if (wificfg_write_string(s, buf) < 0) return -1;; + /* Always close here - expect a new connection. */ + return wificfg_write_string(s, "Content-Length: 0\r\n" + "Connection: close\r\n" + "\r\n"); +} + +int wificfg_write_html_title(int s, char *buf, size_t len, const char *str) +{ + /* Use the hostname or AP SSID as the title prefix. */ + char *hostname = NULL; + sysparam_get_string("hostname", &hostname); + if (!hostname) { + sysparam_get_string("wifi_ap_ssid", &hostname); + } + if (hostname) { + wificfg_html_escape(hostname, buf, len); + free(hostname); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (str) { + if (wificfg_write_string_chunk(s, " ", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, str, buf, len) < 0) return -1; + } + } + + return 0; +} + +static const char *http_wificfg_content[] = { +#include "content/wificfg/index.html" +}; + +static int handle_wificfg_index(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_success_header) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_wificfg_content[0], buf, len) < 0) return -1; + if (wificfg_write_html_title(s, buf, len, "Wifi Config") < 0) return -1; + if (wificfg_write_string_chunk(s, http_wificfg_content[1], buf, len) < 0) return -1; + + char *hostname = NULL; + sysparam_get_string("hostname", &hostname); + if (hostname) { + if (wificfg_write_string_chunk(s, "
Hostname
", buf, len) < 0) { + free(hostname); + return -1; + } + wificfg_html_escape(hostname, buf, len); + free(hostname); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
", buf, len) < 0) return -1; + } + + uint32_t chip_id = sdk_system_get_chip_id(); + snprintf(buf, len, "
Chip ID
%08x
", chip_id); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + snprintf(buf, len, "
Uptime
%u seconds
", + xTaskGetTickCount() * portTICK_PERIOD_MS / 1000); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + snprintf(buf, len, "
Free heap
%u bytes
", (int)xPortGetFreeHeapSize()); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + snprintf(buf, len, "
Flash ID
0x%08x
", sdk_spi_flash_get_id()); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + snprintf(buf, len, "
Flash size
%u KiB
", sdk_flashchip.chip_size >> 10); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, "
LwIP version
" LWIP_VERSION_STRING "
", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
FreeRTOS version
" tskKERNEL_VERSION_NUMBER "
", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
Newlib version
" _NEWLIB_VERSION "
", buf, len) < 0) return -1; + + enum sdk_sleep_type sleep_type = sdk_wifi_get_sleep_type(); + char *sleep_type_str = "??"; + switch (sleep_type) { + case WIFI_SLEEP_NONE: + sleep_type_str = "None"; + break; + case WIFI_SLEEP_LIGHT: + sleep_type_str = "Light"; + break; + case WIFI_SLEEP_MODEM: + sleep_type_str = "Modem"; + break; + default: + break; + } + snprintf(buf, len, "
WiFi sleep type
%s
", sleep_type_str); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + uint8_t opmode = sdk_wifi_get_opmode(); + const char *opmode_str = "??"; + switch (opmode) { + case NULL_MODE: + opmode_str = "Null"; + break; + case STATION_MODE: + opmode_str = "Station"; + break; + case SOFTAP_MODE: + opmode_str = "SoftAP"; + break; + case STATIONAP_MODE: + opmode_str = "StationAP"; + break; + default: + break; + } + snprintf(buf, len, "
OpMode
%s
", opmode_str); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (opmode > NULL_MODE) { + snprintf(buf, len, "
WiFi channel
%u
", sdk_wifi_get_channel()); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + const char *phy_mode_str = "??"; + switch (sdk_wifi_get_phy_mode()) { + case PHY_MODE_11B: + phy_mode_str = "11b"; + break; + case PHY_MODE_11G: + phy_mode_str = "11g"; + break; + case PHY_MODE_11N: + phy_mode_str = "11n"; + break; + default: + break; + } + snprintf(buf, len, "
WiFi physical mode
%s
", phy_mode_str); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (opmode == STATION_MODE || opmode == STATIONAP_MODE) { + uint8_t hwaddr[6]; + if (sdk_wifi_get_macaddr(STATION_IF, hwaddr)) { + if (wificfg_write_string_chunk(s, "
Station MAC address
", buf, len) < 0) return -1; + snprintf(buf, len, "
" MACSTR "
", MAC2STR(hwaddr)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + struct ip_info info; + if (sdk_wifi_get_ip_info(STATION_IF, &info)) { + if (wificfg_write_string_chunk(s, "
Station IP address
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR "
", IP2STR(&info.ip)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
Station netmask
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR "
", IP2STR(&info.netmask)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
Station gateway
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR "
", IP2STR(&info.gw)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + } + + if (opmode == SOFTAP_MODE || opmode == STATIONAP_MODE) { + uint8_t hwaddr[6]; + if (sdk_wifi_get_macaddr(SOFTAP_IF, hwaddr)) { + if (wificfg_write_string_chunk(s, "
AP MAC address
", buf, len) < 0) return -1; + snprintf(buf, len, "
" MACSTR "
", MAC2STR(hwaddr)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + struct ip_info info; + if (sdk_wifi_get_ip_info(SOFTAP_IF, &info)) { + if (wificfg_write_string_chunk(s, "
AP IP address
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR "
", IP2STR(&info.ip)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
AP netmask
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR "
", IP2STR(&info.netmask)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, "
AP gateway
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR "
", IP2STR(&info.gw)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + } + + struct sockaddr addr; + socklen_t addr_len = sizeof(addr); + getpeername(s, (struct sockaddr*)&addr, &addr_len); + + if (addr.sa_family == AF_INET) { + struct sockaddr_in *sa = (struct sockaddr_in *)&addr; + if (wificfg_write_string_chunk(s, "
Peer address
", buf, len) < 0) return -1; + snprintf(buf, len, "
" IPSTR " : %u
", + IP2STR((ip4_addr_t *)&sa->sin_addr.s_addr), ntohs(sa->sin_port)); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wificfg_content[2], buf, len) < 0) return -1; + + char *password = NULL; + sysparam_get_string("cfg_password", &password); + if (password) { + wificfg_html_escape(password, buf, len); + free(password); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wificfg_content[3], buf, len) < 0) return -1; + + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +static int handle_wificfg_index_post(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (content_type != HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED) { + return wificfg_write_string(s, "HTTP/1.1 400 \r\n" + "Content-Type: text/html\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n\r\n"); + } + + size_t rem = content_length; + bool valp = false; + + while (rem > 0) { + int r = wificfg_form_name_value(s, &valp, &rem, buf, len); + + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + form_name name = intern_form_name(buf); + + if (valp) { + int r = wificfg_form_name_value(s, NULL, &rem, buf, len); + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + switch (name) { + case FORM_NAME_CFG_ENABLE: { + uint8_t enable = strtoul(buf, NULL, 10) != 0; + sysparam_set_int8("cfg_enable", enable); + break; + } + case FORM_NAME_CFG_PASSWORD: + sysparam_set_string("cfg_password", buf); + break; + default: + break; + } + } + } + + return wificfg_write_string(s, http_redirect_header); +} + +static const char *http_wifi_station_content[] = { +#include "content/wificfg/sta.html" +}; + +static int handle_wifi_station(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_success_header) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_wifi_station_content[0], buf, len) < 0) return -1; + if (wificfg_write_html_title(s, buf, len, "Wifi station") < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_station_content[1], buf, len) < 0) return -1; + + int8_t wifi_sta_enable = 1; + sysparam_get_int8("wifi_sta_enable", &wifi_sta_enable); + if (wifi_sta_enable && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_station_content[2], buf, len) < 0) return -1; + + int8_t wifi_sta_disabled_restarts = 0; + sysparam_get_int8("wifi_sta_disabled_restarts", &wifi_sta_disabled_restarts); + snprintf(buf, len, "%u", wifi_sta_disabled_restarts); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_station_content[3], buf, len) < 0) return -1; + + char *wifi_sta_ssid = NULL; + sysparam_get_string("wifi_sta_ssid", &wifi_sta_ssid); + if (wifi_sta_ssid) { + wificfg_html_escape(wifi_sta_ssid, buf, len); + free(wifi_sta_ssid); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_station_content[4], buf, len) < 0) return -1; + + char *wifi_sta_password = NULL; + sysparam_get_string("wifi_sta_password", &wifi_sta_password); + if (wifi_sta_password) { + wificfg_html_escape(wifi_sta_password, buf, len); + free(wifi_sta_password); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_station_content[5], buf, len) < 0) return -1; + + char *hostname = NULL; + sysparam_get_string("hostname", &hostname); + if (hostname) { + wificfg_html_escape(hostname, buf, len); + free(hostname); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_station_content[6], buf, len) < 0) return -1; + + int8_t wifi_sta_dhcp = 1; + sysparam_get_int8("wifi_sta_dhcp", &wifi_sta_dhcp); + if (wifi_sta_dhcp && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_station_content[7], buf, len) < 0) return -1; + if (!wifi_sta_dhcp && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_station_content[8], buf, len) < 0) return -1; + + char *wifi_sta_ip_addr = NULL; + sysparam_get_string("wifi_sta_ip_addr", &wifi_sta_ip_addr); + if (wifi_sta_ip_addr) { + wificfg_html_escape(wifi_sta_ip_addr, buf, len); + free(wifi_sta_ip_addr); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_station_content[9], buf, len) < 0) return -1; + + char *wifi_sta_netmask = NULL; + sysparam_get_string("wifi_sta_netmask", &wifi_sta_netmask); + if (wifi_sta_netmask) { + wificfg_html_escape(wifi_sta_netmask, buf, len); + free(wifi_sta_netmask); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_station_content[10], buf, len) < 0) return -1; + + char *wifi_sta_gateway = NULL; + sysparam_get_string("wifi_sta_gateway", &wifi_sta_gateway); + if (wifi_sta_gateway) { + wificfg_html_escape(wifi_sta_gateway, buf, len); + free(wifi_sta_gateway); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_station_content[11], buf, len) < 0) return -1; + + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +static int handle_wifi_station_post(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (content_type != HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED) { + return wificfg_write_string(s, "HTTP/1.1 400 \r\n" + "Content-Type: text/html\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n\r\n"); + } + + size_t rem = content_length; + bool valp = false; + + /* Delay committing some values until all have been read. */ + bool done = false; + uint8_t sta_enable = 0; + + while (rem > 0) { + int r = wificfg_form_name_value(s, &valp, &rem, buf, len); + + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + form_name name = intern_form_name(buf); + + if (valp) { + int r = wificfg_form_name_value(s, NULL, &rem, buf, len); + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + switch (name) { + case FORM_NAME_STA_ENABLE: { + sta_enable = strtoul(buf, NULL, 10) != 0; + break; + } + case FORM_NAME_STA_DISABLED_RESTARTS: { + uint32_t restarts = strtoul(buf, NULL, 10); + if (restarts <= 255) + sysparam_set_int8("wifi_sta_disabled_restarts", restarts); + break; + } + case FORM_NAME_STA_SSID: + sysparam_set_string("wifi_sta_ssid", buf); + break; + case FORM_NAME_STA_PASSWORD: + sysparam_set_string("wifi_sta_password", buf); + break; + case FORM_NAME_HOSTNAME: + sysparam_set_string("hostname", buf); + break; + case FORM_NAME_STA_DHCP: { + uint8_t enable = strtoul(buf, NULL, 10) != 0; + sysparam_set_int8("wifi_sta_dhcp", enable); + break; + } + case FORM_NAME_STA_IP_ADDR: + sysparam_set_string("wifi_sta_ip_addr", buf); + break; + case FORM_NAME_STA_NETMASK: + sysparam_set_string("wifi_sta_netmask", buf); + break; + case FORM_NAME_STA_GATEWAY: + sysparam_set_string("wifi_sta_gateway", buf); + break; + case FORM_NAME_DONE: + done = true; + break; + default: + break; + } + } + } + + if (done) { + sysparam_set_int8("wifi_sta_enable", sta_enable); + } + + return wificfg_write_string(s, http_redirect_header); +} + +static const char *http_wifi_ap_content[] = { +#include "content/wificfg/ap.html" +}; + +static int handle_wifi_ap(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_success_header) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_wifi_ap_content[0], buf, len) < 0) return -1; + if (wificfg_write_html_title(s, buf, len, "Wifi access point") < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_ap_content[1], buf, len) < 0) return -1; + + int8_t wifi_ap_enable = 1; + sysparam_get_int8("wifi_ap_enable", &wifi_ap_enable); + if (wifi_ap_enable && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[2], buf, len) < 0) return -1; + + int8_t wifi_ap_disable_if_sta = 1; + sysparam_get_int8("wifi_ap_disable_if_sta", &wifi_ap_disable_if_sta); + if (wifi_ap_disable_if_sta && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[3], buf, len) < 0) return -1; + + int8_t wifi_ap_disabled_restarts = 0; + sysparam_get_int8("wifi_ap_disabled_restarts", &wifi_ap_disabled_restarts); + snprintf(buf, len, "%u", wifi_ap_disabled_restarts); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[4], buf, len) < 0) return -1; + + char *wifi_ap_ssid = NULL; + sysparam_get_string("wifi_ap_ssid", &wifi_ap_ssid); + if (wifi_ap_ssid) { + wificfg_html_escape(wifi_ap_ssid, buf, len); + free(wifi_ap_ssid); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[5], buf, len) < 0) return -1; + + char *wifi_ap_password = NULL; + sysparam_get_string("wifi_ap_password", &wifi_ap_password); + if (wifi_ap_password) { + wificfg_html_escape(wifi_ap_password, buf, len); + free(wifi_ap_password); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[6], buf, len) < 0) return -1; + + int8_t wifi_ap_ssid_hidden = 0; + sysparam_get_int8("wifi_ap_ssid_hidden", &wifi_ap_ssid_hidden); + if (wifi_ap_ssid_hidden && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[7], buf, len) < 0) return -1; + + int8_t wifi_ap_channel = 6; + sysparam_get_int8("wifi_ap_channel", &wifi_ap_channel); + snprintf(buf, len, "%u", wifi_ap_channel); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[8], buf, len) < 0) return -1; + + int8_t wifi_ap_authmode = 4; + sysparam_get_int8("wifi_ap_authmode", &wifi_ap_authmode); + if (wifi_ap_authmode == 0 && wificfg_write_string_chunk(s, " selected", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_ap_content[9], buf, len) < 0) return -1; + if (wifi_ap_authmode == 1 && wificfg_write_string_chunk(s, " selected", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_ap_content[10], buf, len) < 0) return -1; + if (wifi_ap_authmode == 2 && wificfg_write_string_chunk(s, " selected", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_ap_content[11], buf, len) < 0) return -1; + if (wifi_ap_authmode == 3 && wificfg_write_string_chunk(s, " selected", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_ap_content[12], buf, len) < 0) return -1; + if (wifi_ap_authmode == 4 && wificfg_write_string_chunk(s, " selected", buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[13], buf, len) < 0) return -1; + + int8_t wifi_ap_max_conn = 3; + sysparam_get_int8("wifi_ap_max_conn", &wifi_ap_max_conn); + snprintf(buf, len, "%u", wifi_ap_max_conn); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[14], buf, len) < 0) return -1; + + int32_t wifi_ap_beacon_interval = 100; + sysparam_get_int32("wifi_ap_beacon_interval", &wifi_ap_beacon_interval); + snprintf(buf, len, "%u", wifi_ap_beacon_interval); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[15], buf, len) < 0) return -1; + + char *wifi_ap_ip_addr = NULL; + sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); + if (wifi_ap_ip_addr) { + wificfg_html_escape(wifi_ap_ip_addr, buf, len); + free(wifi_ap_ip_addr); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[16], buf, len) < 0) return -1; + + char *wifi_ap_netmask = NULL; + sysparam_get_string("wifi_ap_netmask", &wifi_ap_netmask); + if (wifi_ap_netmask) { + wificfg_html_escape(wifi_ap_netmask, buf, len); + free(wifi_ap_netmask); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[17], buf, len) < 0) return -1; + + int8_t wifi_ap_dhcp_leases = 4; + sysparam_get_int8("wifi_ap_dhcp_leases", &wifi_ap_dhcp_leases); + snprintf(buf, len, "%u", wifi_ap_dhcp_leases); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) return -1; + + if (wificfg_write_string_chunk(s, http_wifi_ap_content[18], buf, len) < 0) return -1; + + int8_t wifi_ap_dns = 1; + sysparam_get_int8("wifi_ap_dns", &wifi_ap_dns); + if (wifi_ap_dns && wificfg_write_string_chunk(s, "checked", buf, len) < 0) return -1; + if (wificfg_write_string_chunk(s, http_wifi_ap_content[19], buf, len) < 0) return -1; + + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +static int handle_wifi_ap_post(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (content_type != HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED) { + return wificfg_write_string(s, "HTTP/1.1 400 \r\n" + "Content-Type: text/html\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n\r\n"); + } + + size_t rem = content_length; + bool valp = false; + + /* Delay committing some values until all have been read. */ + bool done = false; + uint8_t ap_enable = 0; + uint8_t ap_disable_if_sta = 0; + uint8_t ssid_hidden = 0; + uint8_t dns_enable = 0; + + while (rem > 0) { + int r = wificfg_form_name_value(s, &valp, &rem, buf, len); + + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + form_name name = intern_form_name(buf); + + if (valp) { + int r = wificfg_form_name_value(s, NULL, &rem, buf, len); + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + switch (name) { + case FORM_NAME_AP_ENABLE: { + ap_enable = strtoul(buf, NULL, 10) != 0; + break; + } + case FORM_NAME_AP_DISABLE_IF_STA: { + ap_disable_if_sta = strtoul(buf, NULL, 10) != 0; + break; + } + case FORM_NAME_AP_DISABLED_RESTARTS: { + uint32_t restarts = strtoul(buf, NULL, 10); + if (restarts <= 255) + sysparam_set_int8("wifi_ap_disabled_restarts", restarts); + break; + } + case FORM_NAME_AP_SSID: + sysparam_set_string("wifi_ap_ssid", buf); + break; + case FORM_NAME_AP_PASSWORD: + sysparam_set_string("wifi_ap_password", buf); + break; + case FORM_NAME_AP_SSID_HIDDEN: { + ssid_hidden = strtoul(buf, NULL, 10) != 0; + break; + } + case FORM_NAME_AP_CHANNEL: { + uint32_t channel = strtoul(buf, NULL, 10); + if (channel >= 1 && channel <= 14) + sysparam_set_int8("wifi_ap_channel", channel); + break; + } + case FORM_NAME_AP_AUTHMODE: { + uint32_t mode = strtoul(buf, NULL, 10); + if (mode >= 0 && mode <= 5) + sysparam_set_int8("wifi_ap_authmode", mode); + break; + } + case FORM_NAME_AP_MAX_CONN: { + uint32_t max_conn = strtoul(buf, NULL, 10); + if (max_conn >= 0 && max_conn <= 8) + sysparam_set_int8("wifi_ap_max_conn", max_conn); + break; + } + case FORM_NAME_AP_BEACON_INTERVAL: { + uint32_t interval = strtoul(buf, NULL, 10); + if (interval >= 0 && interval <= 10000) + sysparam_set_int32("wifi_ap_beacon_interval", interval); + break; + } + case FORM_NAME_AP_IP_ADDR: + sysparam_set_string("wifi_ap_ip_addr", buf); + break; + case FORM_NAME_AP_NETMASK: + sysparam_set_string("wifi_ap_netmask", buf); + break; + case FORM_NAME_AP_DHCP_LEASES: { + uint32_t leases = strtoul(buf, NULL, 10); + if (leases >= 0 && leases <= 16) + sysparam_set_int8("wifi_ap_dhcp_leases", leases); + break; + } + case FORM_NAME_AP_DNS: { + dns_enable = strtoul(buf, NULL, 10) != 0; + break; + } + case FORM_NAME_DONE: + done = true; + break; + default: + break; + } + } + } + + if (done) { + sysparam_set_int8("wifi_ap_enable", ap_enable); + sysparam_set_int8("wifi_ap_disable_if_sta", ap_disable_if_sta); + sysparam_set_int8("wifi_ap_ssid_hidden", ssid_hidden); + sysparam_set_int8("wifi_ap_dns", dns_enable); + } + + return wificfg_write_string(s, http_redirect_header); +} + +static bool got_sta_connect = false; +void wificfg_got_sta_connect() +{ + /* Only process this once, to not continue adjusting the settings. */ + if (got_sta_connect) { + return; + } + got_sta_connect = true; + + /* Skip if AP not even enabled. */ + int8_t wifi_ap_enable = 1; + sysparam_get_int8("wifi_ap_enable", &wifi_ap_enable); + if (!wifi_ap_enable) { + return; + } + + int8_t wifi_ap_disable_if_sta = 1; + sysparam_get_int8("wifi_ap_disable_if_sta", &wifi_ap_disable_if_sta); + + if (wifi_ap_disable_if_sta) { + int8_t wifi_ap_disabled_restarts = 0; + sysparam_get_int8("wifi_ap_disabled_restarts", &wifi_ap_disabled_restarts); + if (wifi_ap_disabled_restarts == 0) { + sysparam_set_int8("wifi_ap_disabled_restarts", 1); + } + } +} + +static int handle_restart_post(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + wificfg_write_string(s, http_redirect_header); + close(s); + vTaskDelay(2000 / portTICK_PERIOD_MS); + sdk_system_restart(); + return 0; +} + +static int handle_erase_post(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + wificfg_write_string(s, http_redirect_header); + close(s); + vTaskDelay(2000 / portTICK_PERIOD_MS); + + /* + * Erase the area starting from the sysparams to the end of the flash. + * Configuration information may be in the sdk parameter area too, which is + * in these sectors. + */ + uint32_t num_sectors = 5 + DEFAULT_SYSPARAM_SECTORS; + uint32_t start = sdk_flashchip.chip_size - num_sectors * sdk_flashchip.sector_size; + uint32_t i; + vPortEnterCritical(); + for (i = 0; i < num_sectors; i++) { + spiflash_erase_sector(start + i * sdk_flashchip.sector_size); + } + sdk_system_restart(); + return 0; +} + +/* Minimal not-found response. */ +static const char not_found_header[] = "HTTP/1.1 404 \r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "Cache-Control: no-store\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n" + "\r\n"; + +static const char *http_wificfg_challenge_content[] = { +#include "content/challenge.html" +}; + +static int handle_wificfg_challenge(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_success_header) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_wificfg_challenge_content[0], buf, len) < 0) return -1; + if (wificfg_write_html_title(s, buf, len, "Challenge") < 0) return -1; + if (wificfg_write_string_chunk(s, http_wificfg_challenge_content[1], buf, len) < 0) return -1; + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} + +static int handle_wificfg_challenge_post(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (content_type != HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED) { + return wificfg_write_string(s, "HTTP/1.1 400 \r\n" + "Content-Type: text/html\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n\r\n"); + } + size_t rem = content_length; + bool valp = false; + + int8_t enable = 1; + sysparam_get_int8("cfg_enable", &enable); + char *password = NULL; + sysparam_get_string("cfg_password", &password); + + if (!enable && password && strlen(password)) { + while (rem > 0) { + int r = wificfg_form_name_value(s, &valp, &rem, buf, len); + + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + form_name name = intern_form_name(buf); + + if (valp) { + int r = wificfg_form_name_value(s, NULL, &rem, buf, len); + if (r < 0) { + break; + } + + wificfg_form_url_decode(buf); + + switch (name) { + case FORM_NAME_CFG_PASSWORD: + if (strcmp(password, buf) == 0) + sysparam_set_int8("cfg_enable", 1); + break; + default: + break; + } + } + } + } + + if (password) + free(password); + + return wificfg_write_string(s, http_redirect_header); +} + +#ifdef configUSE_TRACE_FACILITY +static const char *http_tasks_content[] = { +#include "content/tasks.html" +}; + +static int handle_tasks(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len) +{ + if (wificfg_write_string(s, http_success_header) < 0) return -1; + + if (method != HTTP_METHOD_HEAD) { + if (wificfg_write_string_chunk(s, http_tasks_content[0], buf, len) < 0) return -1; + if (wificfg_write_html_title(s, buf, len, "Tasks") < 0) return -1; + if (wificfg_write_string_chunk(s, http_tasks_content[1], buf, len) < 0) return -1; + int num_tasks = uxTaskGetNumberOfTasks(); + TaskStatus_t *task_status = pvPortMalloc(num_tasks * sizeof(TaskStatus_t)); + + if (task_status != NULL) { + int i; + + if (wificfg_write_string_chunk(s, "", buf, len) < 0) { + free(task_status); + return -1; + } + + /* Generate the (binary) data. */ + num_tasks = uxTaskGetSystemState(task_status, num_tasks, NULL); + + /* Create a human readable table from the binary data. */ + for(i = 0; i < num_tasks; i++) { + char cStatus; + switch(task_status[i].eCurrentState) { + case eRunning: cStatus = '*'; break; + case eReady: cStatus = 'R'; break; + case eBlocked: cStatus = 'B'; break; + case eSuspended: cStatus = 'S'; break; + case eDeleted: cStatus = 'D'; break; + default: cStatus = '?'; break; + } + + snprintf(buf, len, "", task_status[i].pcTaskName); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) { + free(task_status); + return -1; + } + snprintf(buf, len, "", + (unsigned int)task_status[i].xTaskNumber, + cStatus); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) { + free(task_status); + return -1; + } + snprintf(buf, len, "", + (unsigned int)task_status[i].uxCurrentPriority, + (unsigned int)task_status[i].uxBasePriority); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) { + free(task_status); + return -1; + } + snprintf(buf, len, "", + (unsigned int)task_status[i].ulRunTimeCounter, + (unsigned int)task_status[i].usStackHighWaterMark); + if (wificfg_write_string_chunk(s, buf, buf, len) < 0) { + free(task_status); + return -1; + } + } + + free(task_status); + + if (wificfg_write_string_chunk(s, "
Task nameTask numberStatusPriorityBase priorityRuntimeStack high-water
%s%u%c%u%u%u%u
", buf, len) < 0) return -1; + } + + if (wificfg_write_string_chunk(s, http_tasks_content[2], buf, len) < 0) return -1; + if (wificfg_write_chunk_end(s) < 0) return -1; + } + return 0; +} +#endif /* configUSE_TRACE_FACILITY */ + +static const wificfg_dispatch wificfg_dispatch_list[] = { + {"/favicon.ico", HTTP_METHOD_GET, handle_favicon, false}, + {"/style.css", HTTP_METHOD_GET, handle_style, false}, + {"/script.js", HTTP_METHOD_GET, handle_script, false}, + {"/", HTTP_METHOD_GET, handle_wificfg_redirect, false}, + {"/index.html", HTTP_METHOD_GET, handle_wificfg_redirect, false}, + {"/wificfg/", HTTP_METHOD_GET, handle_wificfg_index, true}, + {"/wificfg/", HTTP_METHOD_POST, handle_wificfg_index_post, true}, + {"/wificfg/sta.html", HTTP_METHOD_GET, handle_wifi_station, true}, + {"/wificfg/sta.html", HTTP_METHOD_POST, handle_wifi_station_post, true}, + {"/wificfg/ap.html", HTTP_METHOD_GET, handle_wifi_ap, true}, + {"/wificfg/ap.html", HTTP_METHOD_POST, handle_wifi_ap_post, true}, + {"/challenge.html", HTTP_METHOD_GET, handle_wificfg_challenge, false}, + {"/challenge.html", HTTP_METHOD_POST, handle_wificfg_challenge_post, false}, + {"/wificfg/restart.html", HTTP_METHOD_POST, handle_restart_post, true}, + {"/wificfg/erase.html", HTTP_METHOD_POST, handle_erase_post, true}, +#ifdef configUSE_TRACE_FACILITY + {"/tasks", HTTP_METHOD_GET, handle_tasks, false}, + {"/tasks.html", HTTP_METHOD_GET, handle_tasks, false}, +#endif /* configUSE_TRACE_FACILITY */ + {NULL, HTTP_METHOD_ANY, NULL} +}; + +static const wificfg_dispatch wificfg_challenge_dispatch = {"/challenge.html", HTTP_METHOD_GET, handle_wificfg_challenge, false}; + +typedef struct { + int32_t port; + /* + * Two dispatch lists. First is used for the config pages. Second + * can be used to extend the pages handled in app code. + */ + const wificfg_dispatch *wificfg_dispatch; + const wificfg_dispatch *dispatch; +} server_params; + +/* + * The http server uses a single thread to service all requests, one request at + * a time, to keep peak resource usage to a minimum. Keeping connections open + * would cause delays switching between connections. Thus it closes the + * connection after each response. + * + * To help avoid the resource usage of connections in the time-wait state, the + * server asks the client to initiate the connection close and waits a short + * period for it to do so before closing the connection itself. + * + * The response length is always well defined, either sending the content-length + * header or using chunk transfer encoding. Thus the client knows the end of + * responses without the server having to close the connection, and this allows + * the client to close the connection. + * + * Always closing the connection also allows the connection-close header to be + * statically bundled in with the response. + */ +static void server_task(void *pvParameters) +{ + server_params *params = pvParameters; + + struct sockaddr_in serv_addr; + int listenfd = socket(AF_INET, SOCK_STREAM, 0); + memset(&serv_addr, '0', sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(params->port); + bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); + listen(listenfd, 2); + + for (;;) { + int s = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); + if (s >= 0) { + const struct timeval timeout = { 10, 0 }; /* 10 second timeout */ + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + + /* Buffer for reading the request and headers and the post method + * names and values. Also used for building dynamically generated + * responses. */ + char buf[HTTP_BUFFER_SIZE]; + + for (;;) { + /* Read the request line */ + int request_line_size = read_crlf_line(s, buf, sizeof(buf)); + if (request_line_size < 5) { + break; + } + + /* Parse the http method, path, and protocol version. */ + char *method_end = skip_to_whitespace(buf); + char *path_string = skip_whitespace(method_end); + *method_end = 0; + wificfg_method method = intern_http_method(buf); + char *path_end = skip_to_whitespace(path_string); + *path_end = 0; + + /* Dispatch to separate functions to handle the requests. */ + const wificfg_dispatch *match = NULL; + const wificfg_dispatch *dispatch; + + /* + * Check the optional application supplied dispatch table + * first to allow overriding the wifi config paths. + */ + if (params->dispatch) { + for (dispatch = params->dispatch; dispatch->path != NULL; dispatch++) { + if (strcmp(path_string, dispatch->path) == 0 && + (dispatch->method == HTTP_METHOD_ANY || + method == dispatch->method)) { + match = dispatch; + break; + } + } + } + + if (!match) { + for (dispatch = params->wificfg_dispatch; dispatch->path != NULL; dispatch++) { + if (strcmp(path_string, dispatch->path) == 0 && + (dispatch->method == HTTP_METHOD_ANY || + method == dispatch->method)) { + match = dispatch; + break; + } + } + } + + if (match && match->secure) { + /* A secure url so check if enabled. */ + int8_t enable = 1; + sysparam_get_int8("cfg_enable", &enable); + if (!enable) { + /* Is there a recovery password? */ + char *password = NULL; + sysparam_get_string("cfg_password", &password); + if (password && strlen(password) > 0) { + match = &wificfg_challenge_dispatch; + } else { + match = NULL; + } + if (password) + free(password); + } + } + + /* Read the headers, noting some of interest. */ + wificfg_content_type content_type = HTTP_CONTENT_TYPE_OTHER; + bool connection_close = false; + bool hostp = false; + uint32_t host = IPADDR_NONE; + long content_length = 0; + + for (;;) { + int header_length = read_crlf_line(s, buf, sizeof(buf)); + if (header_length <= 0) + break; + + char *name_end = buf; + for (; ; name_end++) { + char c = *name_end; + if (!c || c == ':') + break; + } + if (*name_end == ':') { + char *value = name_end + 1; + *name_end = 0; + http_header header = intern_http_header(buf); + value = skip_whitespace(value); + switch (header) { + case HTTP_HEADER_HOST: + hostp = true; + host = ipaddr_addr(value); + break; + case HTTP_HEADER_CONTENT_LENGTH: + content_length = strtoul(value, NULL, 10); + break; + case HTTP_HEADER_CONTENT_TYPE: + content_type = intern_http_content_type(value); + break; + case HTTP_HEADER_CONNECTION: + connection_close = strcmp(value, "close") == 0; + break; + default: + break; + } + } + } + + if (hostp && host == IPADDR_NONE) { + /* Redirect to an IP address. */ + handle_ipaddr_redirect(s, buf, sizeof(buf)); + /* Close the connection. */ + break; + } else if (match) { + if ((*match->handler)(s, method, content_length, content_type, buf, sizeof(buf)) < 0) break; + } else { + if (wificfg_write_string(s, not_found_header) < 0) break; + } + + /* + * At this point the client is expected to close the connection, + * so wait briefly for it to do so before giving up. While here + * consume any excess input to avoid a connection reset - this + * can happen if the handler aborted early. + */ + const struct timeval timeout1 = { 1, 0 }; /* 1 second timeout */ + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout1, sizeof(timeout1)); + size_t len; + for (len = 0; len < 4096; len++) { + char c; + int res = read(s, &c, 1); + if (res != 1) break; + } + + if (connection_close) + break; + + /* Close anyway. */ + break; + } + + close(s); + + if (sdk_wifi_station_get_connect_status() == STATION_GOT_IP) { + wificfg_got_sta_connect(); + } + } + } +} + + +static void dns_task(void *pvParameters) +{ + char *wifi_ap_ip_addr = NULL; + sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); + if (!wifi_ap_ip_addr) { + printf("dns: no ip address\n"); + vTaskDelete(NULL); + } + ip4_addr_t server_addr; + server_addr.addr = ipaddr_addr(wifi_ap_ip_addr); + + struct sockaddr_in serv_addr; + int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + memset(&serv_addr, '0', sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(53); + bind(fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); + + const struct ifreq ifreq0 = { "en0" }; + const struct ifreq ifreq1 = { "en1" }; + lwip_setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, + sdk_wifi_get_opmode() == STATIONAP_MODE ? &ifreq1 : &ifreq0, + sizeof(ifreq0)); + + for (;;) { + char buffer[96]; + struct sockaddr src_addr; + socklen_t src_addr_len = sizeof(src_addr); + size_t count = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&src_addr, &src_addr_len); + + /* Drop messages that are too large to send a response in the buffer */ + if (count > 0 && count <= sizeof(buffer) - 16 && src_addr.sa_family == AF_INET) { + size_t qname_len = strlen(buffer + 12) + 1; + uint32_t reply_len = 2 + 10 + qname_len + 16 + 4; + + char *head = buffer + 2; + *head++ = 0x80; // Flags + *head++ = 0x00; + *head++ = 0x00; // Q count + *head++ = 0x01; + *head++ = 0x00; // A count + *head++ = 0x01; + *head++ = 0x00; // Auth count + *head++ = 0x00; + *head++ = 0x00; // Add count + *head++ = 0x00; + head += qname_len; + *head++ = 0x00; // Q type + *head++ = 0x01; + *head++ = 0x00; // Q class + *head++ = 0x01; + *head++ = 0xC0; // LBL offs + *head++ = 0x0C; + *head++ = 0x00; // Type + *head++ = 0x01; + *head++ = 0x00; // Class + *head++ = 0x01; + *head++ = 0x00; // TTL + *head++ = 0x00; + *head++ = 0x00; + *head++ = 0x78; + *head++ = 0x00; // RD len + *head++ = 0x04; + *head++ = ip4_addr1(&server_addr); + *head++ = ip4_addr2(&server_addr); + *head++ = ip4_addr3(&server_addr); + *head++ = ip4_addr4(&server_addr); + + sendto(fd, buffer, reply_len, 0, &src_addr, src_addr_len); + } + } +} + + +void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch) +{ + char *wifi_sta_ssid = NULL; + char *wifi_sta_password = NULL; + char *wifi_ap_ssid = NULL; + char *wifi_ap_password = NULL; + + uint32_t base_addr; + uint32_t num_sectors; + if (sysparam_get_info(&base_addr, &num_sectors) != SYSPARAM_OK) { + printf("Warning: WiFi config, sysparam not initialized\n"); + return; + } + + sysparam_get_string("wifi_ap_ssid", &wifi_ap_ssid); + sysparam_get_string("wifi_ap_password", &wifi_ap_password); + sysparam_get_string("wifi_sta_ssid", &wifi_sta_ssid); + sysparam_get_string("wifi_sta_password", &wifi_sta_password); + + int8_t wifi_sta_enable = 1; + int8_t wifi_ap_enable = 1; + sysparam_get_int8("wifi_sta_enable", &wifi_sta_enable); + sysparam_get_int8("wifi_ap_enable", &wifi_ap_enable); + + int8_t wifi_sta_disabled_restarts = 0; + sysparam_get_int8("wifi_sta_disabled_restarts", &wifi_sta_disabled_restarts); + if (wifi_sta_disabled_restarts > 0) { + wifi_sta_enable = 0; + wifi_sta_disabled_restarts--; + sysparam_set_int8("wifi_sta_disabled_restarts", wifi_sta_disabled_restarts); + } + + int8_t wifi_ap_disabled_restarts = 0; + sysparam_get_int8("wifi_ap_disabled_restarts", &wifi_ap_disabled_restarts); + if (wifi_ap_disabled_restarts > 0) { + wifi_ap_enable = 0; + wifi_ap_disabled_restarts--; + sysparam_set_int8("wifi_ap_disabled_restarts", wifi_ap_disabled_restarts); + } + + /* Validate the configuration. */ + + if (wifi_sta_enable && (!wifi_sta_ssid || !wifi_sta_password || + strlen(wifi_sta_ssid) < 1 || + strlen(wifi_sta_ssid) > 32 || + !wifi_sta_password || + strlen(wifi_sta_password) < 8 || + strlen(wifi_sta_password) >= 64)) { + wifi_sta_enable = 0; + } + + if (wifi_ap_enable) { + /* Default AP ssid and password. */ + if (!wifi_ap_ssid && wificfg_default_ssid) { + uint8_t macaddr[6]; + char ssid[32]; + sdk_wifi_get_macaddr(1, macaddr); + snprintf(ssid, sizeof(ssid), wificfg_default_ssid, macaddr[3], + macaddr[4], macaddr[5]); + sysparam_set_string("wifi_ap_ssid", ssid); + sysparam_get_string("wifi_ap_ssid", &wifi_ap_ssid); + + if (!wifi_ap_password && wificfg_default_password) { + sysparam_set_string("wifi_ap_password", wificfg_default_password); + sysparam_get_string("wifi_ap_password", &wifi_ap_password); + } + } + + /* If the ssid and password are not valid then disable the AP interface. */ + if (!wifi_ap_ssid || strlen(wifi_ap_ssid) < 1 || strlen(wifi_ap_ssid) >= 32 || + !wifi_ap_password || strlen(wifi_ap_ssid) < 8 || strlen(wifi_ap_password) >= 64) { + wifi_ap_enable = 0; + } + } + + int8_t wifi_mode = NULL_MODE; + if (wifi_sta_enable && wifi_ap_enable) + wifi_mode = STATIONAP_MODE; + else if (wifi_sta_enable) + wifi_mode = STATION_MODE; + else + wifi_mode = SOFTAP_MODE; + sdk_wifi_set_opmode(wifi_mode); + + if (wifi_sta_enable) { + /* Default a hostname. */ + char *hostname = NULL; + sysparam_get_string("hostname", &hostname); + if (!hostname && wificfg_default_hostname) { + uint8_t macaddr[6]; + char name[32]; + sdk_wifi_get_macaddr(1, macaddr); + snprintf(name, sizeof(name), wificfg_default_hostname, macaddr[3], + macaddr[4], macaddr[5]); + sysparam_set_string("hostname", name); + } + if (hostname) { + free(hostname); + } + + struct sdk_station_config config; + strcpy((char *)config.ssid, wifi_sta_ssid); + strcpy((char *)config.password, wifi_sta_password); + config.bssid_set = 0; + + int8_t wifi_sta_dhcp = 1; + sysparam_get_int8("wifi_sta_dhcp", &wifi_sta_dhcp); + + if (!wifi_sta_dhcp) { + char *wifi_sta_ip_addr = NULL; + char *wifi_sta_netmask = NULL; + char *wifi_sta_gateway = NULL; + sysparam_get_string("wifi_sta_ip_addr", &wifi_sta_ip_addr); + sysparam_get_string("wifi_sta_netmask", &wifi_sta_netmask); + sysparam_get_string("wifi_sta_gateway", &wifi_sta_gateway); + + if (wifi_sta_ip_addr && strlen(wifi_sta_ip_addr) > 4 && + wifi_sta_netmask && strlen(wifi_sta_netmask) > 4 && + wifi_sta_gateway && strlen(wifi_sta_gateway) > 4) { + sdk_wifi_station_dhcpc_stop(); + struct ip_info info; + memset(&info, 0x0, sizeof(info)); + info.ip.addr = ipaddr_addr(wifi_sta_ip_addr); + info.netmask.addr = ipaddr_addr(wifi_sta_netmask); + info.gw.addr = ipaddr_addr(wifi_sta_gateway); + sdk_wifi_set_ip_info(STATION_IF, &info); + } + if (wifi_sta_ip_addr) free(wifi_sta_ip_addr); + if (wifi_sta_netmask) free(wifi_sta_netmask); + if (wifi_sta_gateway) free(wifi_sta_gateway); + } + + sdk_wifi_station_set_config(&config); + } + + if (wifi_ap_enable) { + /* Read and validate paramenters. */ + int8_t wifi_ap_ssid_hidden = 0; + sysparam_get_int8("wifi_ap_ssid_hidden", &wifi_ap_ssid_hidden); + if (wifi_ap_ssid_hidden < 0 || wifi_ap_ssid_hidden > 1) + wifi_ap_ssid_hidden = 1; + + int8_t wifi_ap_channel = 6; + sysparam_get_int8("wifi_ap_channel", &wifi_ap_channel); + + /* AU does not allow channels above 13, although 14 works. */ + if (wifi_ap_channel > 13) { + wifi_ap_channel = 13; + } +#if 0 + /* US does not allow channels above 11, although they work. */ + if (wifi_ap_channel > 11) { + wifi_ap_channel = 11; + } +#endif + if (wifi_ap_channel < 1 || wifi_ap_channel > 14) { + wifi_ap_channel = 6; + } + + int8_t wifi_ap_authmode = AUTH_WPA_WPA2_PSK; + sysparam_get_int8("wifi_ap_authmode", &wifi_ap_authmode); + if (wifi_ap_authmode < AUTH_OPEN || wifi_ap_authmode > AUTH_MAX) + wifi_ap_authmode = AUTH_WPA_WPA2_PSK; + + int8_t wifi_ap_max_conn = 3; + sysparam_get_int8("wifi_ap_max_conn", &wifi_ap_max_conn); + if (wifi_ap_max_conn < 1 || wifi_ap_max_conn > 8) + wifi_ap_max_conn = 3; + + int32_t wifi_ap_beacon_interval = 100; + sysparam_get_int32("wifi_ap_beacon_interval", &wifi_ap_beacon_interval); + if (wifi_ap_beacon_interval < 0 || wifi_ap_beacon_interval > 1000) + wifi_ap_beacon_interval = 100; + + /* Default AP IP address and netmask. */ + char *wifi_ap_ip_addr = NULL; + sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); + if (!wifi_ap_ip_addr) { + sysparam_set_string("wifi_ap_ip_addr", "172.16.0.1"); + sysparam_get_string("wifi_ap_ip_addr", &wifi_ap_ip_addr); + } + char *wifi_ap_netmask = NULL; + sysparam_get_string("wifi_ap_netmask", &wifi_ap_netmask); + if (!wifi_ap_netmask) { + sysparam_set_string("wifi_ap_netmask", "255.255.0.0"); + sysparam_get_string("wifi_ap_netmask", &wifi_ap_netmask); + } + + if (strlen(wifi_ap_ip_addr) >= 7 && strlen(wifi_ap_netmask) >= 7) { + struct ip_info ap_ip; + ap_ip.ip.addr = ipaddr_addr(wifi_ap_ip_addr); + ap_ip.netmask.addr = ipaddr_addr(wifi_ap_netmask); + IP4_ADDR(&ap_ip.gw, 0, 0, 0, 0); + sdk_wifi_set_ip_info(1, &ap_ip); + + struct sdk_softap_config ap_config = { + .ssid_hidden = wifi_ap_ssid_hidden, + .channel = wifi_ap_channel, + .authmode = wifi_ap_authmode, + .max_connection = wifi_ap_max_conn, + .beacon_interval = wifi_ap_beacon_interval, + }; + strcpy((char *)ap_config.ssid, wifi_ap_ssid); + ap_config.ssid_len = strlen(wifi_ap_ssid); + strcpy((char *)ap_config.password, wifi_ap_password); + sdk_wifi_softap_set_config(&ap_config); + + int8_t wifi_ap_dhcp_leases = 4; + sysparam_get_int8("wifi_ap_dhcp_leases", &wifi_ap_dhcp_leases); + + if (wifi_ap_dhcp_leases) { + ip4_addr_t first_client_ip; + first_client_ip.addr = ap_ip.ip.addr + htonl(1); + + int8_t wifi_ap_dns = 1; + sysparam_get_int8("wifi_ap_dns", &wifi_ap_dns); + if (wifi_ap_dns < 0 || wifi_ap_dns > 1) + wifi_ap_dns = 1; + + dhcpserver_start(&first_client_ip, wifi_ap_dhcp_leases); + dhcpserver_set_router(&ap_ip.ip); + if (wifi_ap_dns) { + dhcpserver_set_dns(&ap_ip.ip); + xTaskCreate(dns_task, "WiFi Cfg DNS", 384, NULL, 2, NULL); + } + } + } + + free(wifi_ap_ip_addr); + free(wifi_ap_netmask); + } + + if (wifi_sta_ssid) free(wifi_sta_ssid); + if (wifi_sta_password) free(wifi_sta_password); + if (wifi_ap_ssid) free(wifi_ap_ssid); + if (wifi_ap_password) free(wifi_ap_password); + + server_params *params = malloc(sizeof(server_params)); + params->port = port; + params->wificfg_dispatch = wificfg_dispatch_list; + params->dispatch = dispatch; + + xTaskCreate(server_task, "WiFi Cfg HTTP", 464, params, 2, NULL); +} diff --git a/extras/wificfg/wificfg.h b/extras/wificfg/wificfg.h new file mode 100644 index 0000000..705b2f6 --- /dev/null +++ b/extras/wificfg/wificfg.h @@ -0,0 +1,137 @@ +/* + * WiFi configuration via a simple web server. + * + * Copyright (C) 2016 OurAirQuality.org + * + * Licensed under the Apache License, Version 2.0, January 2004 (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/ + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS WITH THE SOFTWARE. + * + */ + +#ifndef __WIFICFG_H__ +#define __WIFICFG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Printf format used to initialize a default AP ssid. It is passed the last + * three bytes of the mac address. This may be NULL to not default the ssid, + * but the AP network will not run without a ssid. + */ +extern char *wificfg_default_ssid; + +/* + * A default password for the AP interface. This may be NULL to not default the + * password, but the AP network will not run without a password. The minimum + * length is 8 characters. + */ +extern char *wificfg_default_password; + +/* + * A default hostname printf format string. This may be NULL to not default the + * hostname. + */ +extern char *wificfg_default_hostname; + +/* + * The web server parses the http method string in these enums. The ANY method + * is only use for dispatch. The method enum is passed to the handler functions. + */ +typedef enum { + HTTP_METHOD_GET, + HTTP_METHOD_POST, + HTTP_METHOD_HEAD, + HTTP_METHOD_OTHER, + HTTP_METHOD_ANY, +} wificfg_method; + +/* + * The web server parses these content-type header values. This is passed to the + * dispatch function. + */ +typedef enum { + HTTP_CONTENT_TYPE_WWW_FORM_URLENCODED, + HTTP_CONTENT_TYPE_OTHER +} wificfg_content_type; + +/* + * The function signature for the http server request handler functions. + * + * The buffer, with its length, is usable by the handler. + */ +typedef int (* wificfg_handler)(int s, wificfg_method method, + uint32_t content_length, + wificfg_content_type content_type, + char *buf, size_t len); + +typedef struct { + const char *path; + wificfg_method method; + wificfg_handler handler; + bool secure; +} wificfg_dispatch; + + +/* + * Start the Wifi Configuration http server task. The IP port number + * and a path dispatch list are needed. The dispatch list can not be + * stack allocated as it is passed to another task. + */ +void wificfg_init(uint32_t port, const wificfg_dispatch *dispatch); + +/* + * Support for reading a form name or value from the socket. The name or value + * is truncated to the buffer length. The number of characters read is limited + * to the remainder which is updated. The 'valp' flag is set if a value follows. + */ +int wificfg_form_name_value(int s, bool *valp, size_t *rem, char *buf, size_t len); + +/* Support for form url-encoding decoder. */ +void wificfg_form_url_decode(char *string); + +/* Support for html-escaping of form values. */ +void wificfg_html_escape(char *string, char *buf, size_t len); + +/* Support for writing a string in a response. */ +int wificfg_write_string(int s, const char *str); + +/* Support for writing a string in a response, with chunk transfer encoding. + * An optional buffer may be supplied to use to construct a chunk with the + * header and trailer, reducing the number of write() calls, and the str may be + * at the start of this buffer. + */ +int wificfg_write_string_chunk(int s, const char *str, char *buf, size_t len); + +/* Write a chunk transfer encoding end marker. */ +int wificfg_write_chunk_end(int s); + +/* Write a chunk offset 4 bytes into the buffer. */ +int wificfg_write_buffer_chunk(int s, char *buf); + +/* Write a html title meta data, using the hostname or AP SSI. */ +int wificfg_write_html_title(int s, char *buf, size_t len, const char *str); + +/* Callback to notify the wificfg logic that a station connection has been + * successfully established. It might use this to disable the AP interface after + * a restart. + */ +void wificfg_got_sta_connect(void); + +#ifdef __cplusplus +} +#endif + +#endif // __WIFICFG_H__ diff --git a/extras/ws2812_i2s/ws2812_i2s.c b/extras/ws2812_i2s/ws2812_i2s.c index 310869b..62dc496 100644 --- a/extras/ws2812_i2s/ws2812_i2s.c +++ b/extras/ws2812_i2s/ws2812_i2s.c @@ -37,7 +37,7 @@ #endif #define MAX_DMA_BLOCK_SIZE 4095 -#define DMA_PIXEL_SIZE 12 // each colour takes 4 bytes +// #define DMA_PIXEL_SIZE 16 // each colour takes 4 bytes /** * Amount of zero data to produce WS2812 reset condition. @@ -60,7 +60,7 @@ volatile uint32_t dma_isr_counter = 0; static volatile bool i2s_dma_processing = false; -static void dma_isr_handler(void) +static void dma_isr_handler(void *arg) { if (i2s_dma_is_eof_interrupt()) { #ifdef WS2812_I2S_DEBUG @@ -117,9 +117,9 @@ static inline void init_descriptors_list(uint8_t *buf, uint32_t total_dma_data_s } } -void ws2812_i2s_init(uint32_t pixels_number) +void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type) { - dma_buffer_size = pixels_number * DMA_PIXEL_SIZE; + dma_buffer_size = pixels_number * type; dma_block_list_size = dma_buffer_size / MAX_DMA_BLOCK_SIZE; if (dma_buffer_size % MAX_DMA_BLOCK_SIZE) { @@ -145,7 +145,7 @@ void ws2812_i2s_init(uint32_t pixels_number) debug("i2s clock dividers, bclk=%d, clkm=%d\n", clock_div.bclk_div, clock_div.clkm_div); - i2s_dma_init(dma_isr_handler, clock_div, i2s_pins); + i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins); } const IRAM_DATA int16_t bitpatterns[16] = @@ -156,13 +156,13 @@ const IRAM_DATA int16_t bitpatterns[16] = 0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110, }; -void ws2812_i2s_update(ws2812_pixel_t *pixels) +void ws2812_i2s_update(ws2812_pixel_t *pixels, pixeltype_t type) { while (i2s_dma_processing) {}; uint16_t *p_dma_buf = dma_buffer; - for (uint32_t i = 0; i < (dma_buffer_size / DMA_PIXEL_SIZE); i++) { + for (uint32_t i = 0; i < (dma_buffer_size / type); i++) { // green *p_dma_buf++ = bitpatterns[pixels[i].green & 0x0F]; *p_dma_buf++ = bitpatterns[pixels[i].green >> 4]; @@ -174,6 +174,12 @@ void ws2812_i2s_update(ws2812_pixel_t *pixels) // blue *p_dma_buf++ = bitpatterns[pixels[i].blue & 0x0F]; *p_dma_buf++ = bitpatterns[pixels[i].blue >> 4]; + + if(type == PIXEL_RGBW) { + // white + *p_dma_buf++ = bitpatterns[pixels[i].white & 0x0F]; + *p_dma_buf++ = bitpatterns[pixels[i].white >> 4]; + } } i2s_dma_processing = true; diff --git a/extras/ws2812_i2s/ws2812_i2s.h b/extras/ws2812_i2s/ws2812_i2s.h index f6ebc82..16956dc 100644 --- a/extras/ws2812_i2s/ws2812_i2s.h +++ b/extras/ws2812_i2s/ws2812_i2s.h @@ -35,8 +35,14 @@ typedef struct { uint8_t red; uint8_t green; uint8_t blue; + uint8_t white; } ws2812_pixel_t; +typedef enum { + PIXEL_RGB = 12, + PIXEL_RGBW = 16 +} pixeltype_t; + /** * Initialize i2s and dma subsystems to work with ws2812 led strip. * @@ -44,7 +50,7 @@ typedef struct { * * @param pixels_number Number of pixels in the strip. */ -void ws2812_i2s_init(uint32_t pixels_number); +void ws2812_i2s_init(uint32_t pixels_number, pixeltype_t type); /** * Update ws2812 pixels. @@ -52,7 +58,7 @@ void ws2812_i2s_init(uint32_t pixels_number); * @param pixels Array of 'pixels_number' pixels. The array must contain all * the pixels. */ -void ws2812_i2s_update(ws2812_pixel_t *pixels); +void ws2812_i2s_update(ws2812_pixel_t *pixels, pixeltype_t type); #ifdef __cplusplus } diff --git a/include/espressif/esp_wifi.h b/include/espressif/esp_wifi.h index 5d9ba19..8932974 100644 --- a/include/espressif/esp_wifi.h +++ b/include/espressif/esp_wifi.h @@ -44,9 +44,9 @@ enum { }; struct ip_info { - struct ip_addr ip; - struct ip_addr netmask; - struct ip_addr gw; + struct ip4_addr ip; + struct ip4_addr netmask; + struct ip4_addr gw; }; bool sdk_wifi_get_ip_info(uint8_t if_index, struct ip_info *info); diff --git a/include/espressif/sdk_private.h b/include/espressif/sdk_private.h index fa643a7..7ae4336 100644 --- a/include/espressif/sdk_private.h +++ b/include/espressif/sdk_private.h @@ -20,7 +20,7 @@ extern "C" { #endif -struct ip_addr; +struct ip4_addr; /********************************************* * Defined in libmain.a @@ -43,17 +43,6 @@ int sdk_uart_rx_one_char(char *buf); */ void sdk_os_putc(char c); -/* Called when an IP gets set on the "station" (client) interface. - */ -void sdk_system_station_got_ip_set(struct ip_addr *ip_addr, struct ip_addr *sn_mask, struct ip_addr *gw_addr); - -/* This is a no-op wrapper around ppRecycleRxPkt, which is defined in libpp.a - - It's called when a pbuf is freed, and allows pp to reuse the 'eb' pointer to ESP-specific - pbuf data. (See esp-lwip pbuf.h) - */ -void sdk_system_pp_recycle_rx_pkt(void *eb); - #ifdef __cplusplus } #endif diff --git a/lib/allsymbols.rename b/lib/allsymbols.rename index 5425845..cf30bc9 100644 --- a/lib/allsymbols.rename +++ b/lib/allsymbols.rename @@ -289,6 +289,7 @@ os_timer_disarm sdk_os_timer_disarm os_timer_setfn sdk_os_timer_setfn os_update_cpu_frequency sdk_os_update_cpu_frequency pbkdf2_sha1 sdk_pbkdf2_sha1 +pbuf_alloc sdk_pbuf_alloc pbus_set_rxbbgain sdk_pbus_set_rxbbgain pend_flag_noise_check sdk_pend_flag_noise_check pend_flag_periodic_cal sdk_pend_flag_periodic_cal diff --git a/lib/libmain.a b/lib/libmain.a index 60657ec..cd6f83a 100644 Binary files a/lib/libmain.a and b/lib/libmain.a differ diff --git a/lib/libmain.remove b/lib/libmain.remove index 35145b3..158fba7 100644 --- a/lib/libmain.remove +++ b/lib/libmain.remove @@ -3,3 +3,4 @@ printf-stdarg.o libc.o xtensa_vectors.o app_main.o +ets_timer.o diff --git a/lib/libnet80211.a b/lib/libnet80211.a index 4a36331..1146020 100644 Binary files a/lib/libnet80211.a and b/lib/libnet80211.a differ diff --git a/lib/libpp.a b/lib/libpp.a index 2747863..39631a2 100644 Binary files a/lib/libpp.a and b/lib/libpp.a differ diff --git a/lib/libwpa.a b/lib/libwpa.a index a8fa39a..1c99007 100644 Binary files a/lib/libwpa.a and b/lib/libwpa.a differ diff --git a/libc/README.md b/libc/README.md index 0a2941d..f4d8199 100644 --- a/libc/README.md +++ b/libc/README.md @@ -1,3 +1 @@ -Newlib 2.2.0 with xtensa & locking patches, built from commit daa6ae40cdc8099f54c3e68a586fc1b906169c5a - -For details on newlib in esp-open-rtos, see https://github.com/SuperHouse/esp-open-rtos/wiki/libc-configuration +Newlib from git://sourceware.org/git/newlib-cygwin.git with xtensa & locking patches see https://github.com/ourairquality/newlib and built from commit 7bcbbff5f7e3600806f352e88ec23ae0300edc29 diff --git a/libc/share/info/configure.info b/libc/share/info/configure.info deleted file mode 100644 index eccae2a..0000000 --- a/libc/share/info/configure.info +++ /dev/null @@ -1,2721 +0,0 @@ -This is configure.info, produced by makeinfo version 6.0 from -configure.texi. - -INFO-DIR-SECTION GNU admin -START-INFO-DIR-ENTRY -* configure: (configure). The GNU configure and build system -END-INFO-DIR-ENTRY - -This file documents the GNU configure and build system. - - Copyright (C) 1998 Cygnus Solutions. - - Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - - Permission is granted to copy and distribute modified versions of -this manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - - Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be stated in a -translation approved by the Foundation. - - -File: configure.info, Node: Top, Next: Introduction, Up: (dir) - -GNU configure and build system -****************************** - -The GNU configure and build system. - -* Menu: - -* Introduction:: Introduction. -* Getting Started:: Getting Started. -* Files:: Files. -* Configuration Names:: Configuration Names. -* Cross Compilation Tools:: Cross Compilation Tools. -* Canadian Cross:: Canadian Cross. -* Cygnus Configure:: Cygnus Configure. -* Multilibs:: Multilibs. -* FAQ:: Frequently Asked Questions. -* Index:: Index. - - -File: configure.info, Node: Introduction, Next: Getting Started, Prev: Top, Up: Top - -1 Introduction -************** - -This document describes the GNU configure and build systems. It -describes how autoconf, automake, libtool, and make fit together. It -also includes a discussion of the older Cygnus configure system. - - This document does not describe in detail how to use each of the -tools; see the respective manuals for that. Instead, it describes which -files the developer must write, which files are machine generated and -how they are generated, and where certain common problems should be -addressed. - - This document draws on several sources, including the autoconf manual -by David MacKenzie (*note autoconf overview: (autoconf)Top.), the -automake manual by David MacKenzie and Tom Tromey (*note automake -overview: (automake)Top.), the libtool manual by Gordon Matzigkeit -(*note libtool overview: (libtool)Top.), and the Cygnus configure manual -by K. Richard Pixley. - -* Menu: - -* Goals:: Goals. -* Tools:: The tools. -* History:: History. -* Building:: Building. - - -File: configure.info, Node: Goals, Next: Tools, Up: Introduction - -1.1 Goals -========= - -The GNU configure and build system has two main goals. - - The first is to simplify the development of portable programs. The -system permits the developer to concentrate on writing the program, -simplifying many details of portability across Unix and even Windows -systems, and permitting the developer to describe how to build the -program using simple rules rather than complex Makefiles. - - The second is to simplify the building of programs distributed as -source code. All programs are built using a simple, standardized, two -step process. The program builder need not install any special tools in -order to build the program. - - -File: configure.info, Node: Tools, Next: History, Prev: Goals, Up: Introduction - -1.2 Tools -========= - -The GNU configure and build system is comprised of several different -tools. Program developers must build and install all of these tools. - - People who just want to build programs from distributed sources -normally do not need any special tools beyond a Unix shell, a make -program, and a C compiler. - -autoconf - provides a general portability framework, based on testing the - features of the host system at build time. -automake - a system for describing how to build a program, permitting the - developer to write a simplified 'Makefile'. -libtool - a standardized approach to building shared libraries. -gettext - provides a framework for translation of text messages into other - languages; not really discussed in this document. -m4 - autoconf requires the GNU version of m4; the standard Unix m4 does - not suffice. -perl - automake requires perl. - - -File: configure.info, Node: History, Next: Building, Prev: Tools, Up: Introduction - -1.3 History -=========== - -This is a very brief and probably inaccurate history. - - As the number of Unix variants increased during the 1980s, it became -harder to write programs which could run on all variants. While it was -often possible to use '#ifdef' to identify particular systems, -developers frequently did not have access to every system, and the -characteristics of some systems changed from version to version. - - By 1992, at least three different approaches had been developed: - * The Metaconfig program, by Larry Wall, Harlan Stenn, and Raphael - Manfredi. - * The Cygnus configure script, by K. Richard Pixley, and the gcc - configure script, by Richard Stallman. These use essentially the - same approach, and the developers communicated regularly. - * The autoconf program, by David MacKenzie. - - The Metaconfig program is still used for Perl and a few other -programs. It is part of the Dist package. I do not know if it is being -developed. - - In 1994, David MacKenzie and others modified autoconf to incorporate -all the features of Cygnus configure. Since then, there has been a slow -but steady conversion of GNU programs from Cygnus configure to autoconf. -gcc has been converted, eliminating the gcc configure script. - - GNU autoconf was regularly maintained until late 1996. As of this -writing in June, 1998, it has no public maintainer. - - Most programs are built using the make program, which requires the -developer to write Makefiles describing how to build the programs. -Since most programs are built in pretty much the same way, this led to a -lot of duplication. - - The X Window system is built using the imake tool, which uses a -database of rules to eliminate the duplication. However, building a -tool which was developed using imake requires that the builder have -imake installed, violating one of the goals of the GNU system. - - The new BSD make provides a standard library of Makefile fragments, -which permits developers to write very simple Makefiles. However, this -requires that the builder install the new BSD make program. - - In 1994, David MacKenzie wrote the first version of automake, which -permitted writing a simple build description which was converted into a -Makefile which could be used by the standard make program. In 1995, Tom -Tromey completely rewrote automake in Perl, and he continues to enhance -it. - - Various free packages built libraries, and by around 1995 several -included support to build shared libraries on various platforms. -However, there was no consistent approach. In early 1996, Gordon -Matzigkeit began working on libtool, which provided a standardized -approach to building shared libraries. This was integrated into -automake from the start. - - The development of automake and libtool was driven by the GNITS -project, a group of GNU maintainers who designed standardized tools to -help meet the GNU coding standards. - - -File: configure.info, Node: Building, Prev: History, Up: Introduction - -1.4 Building -============ - -Most readers of this document should already know how to build a tool by -running 'configure' and 'make'. This section may serve as a quick -introduction or reminder. - - Building a tool is normally as simple as running 'configure' followed -by 'make'. You should normally run 'configure' from an empty directory, -using some path to refer to the 'configure' script in the source -directory. The directory in which you run 'configure' is called the -"object directory". - - In order to use a object directory which is different from the source -directory, you must be using the GNU version of 'make', which has the -required 'VPATH' support. Despite this restriction, using a different -object directory is highly recommended: - * It keeps the files generated during the build from cluttering up - your sources. - * It permits you to remove the built files by simply removing the - entire build directory. - * It permits you to build from the same sources with several sets of - configure options simultaneously. - - If you don't have GNU 'make', you will have to run 'configure' in the -source directory. All GNU packages should support this; in particular, -GNU packages should not assume the presence of GNU 'make'. - - After running 'configure', you can build the tools by running 'make'. - - To install the tools, run 'make install'. Installing the tools will -copy the programs and any required support files to the "installation -directory". The location of the installation directory is controlled by -'configure' options, as described below. - - In the Cygnus tree at present, the info files are built and installed -as a separate step. To build them, run 'make info'. To install them, -run 'make install-info'. The equivalent html files are also built and -installed in a separate step. To build the html files, run 'make html'. -To install the html files run 'make install-html'. - - All 'configure' scripts support a wide variety of options. The most -interesting ones are '--with' and '--enable' options which are generally -specific to particular tools. You can usually use the '--help' option -to get a list of interesting options for a particular configure script. - - The only generic options you are likely to use are the '--prefix' and -'--exec-prefix' options. These options are used to specify the -installation directory. - - The directory named by the '--prefix' option will hold machine -independent files such as info files. - - The directory named by the '--exec-prefix' option, which is normally -a subdirectory of the '--prefix' directory, will hold machine dependent -files such as executables. - - The default for '--prefix' is '/usr/local'. The default for -'--exec-prefix' is the value used for '--prefix'. - - The convention used in Cygnus releases is to use a '--prefix' option -of '/usr/cygnus/RELEASE', where RELEASE is the name of the release, and -to use a '--exec-prefix' option of '/usr/cygnus/RELEASE/H-HOST', where -HOST is the configuration name of the host system (*note Configuration -Names::). - - Do not use either the source or the object directory as the -installation directory. That will just lead to confusion. - - -File: configure.info, Node: Getting Started, Next: Files, Prev: Introduction, Up: Top - -2 Getting Started -***************** - -To start using the GNU configure and build system with your software -package, you must write three files, and you must run some tools to -manually generate additional files. - -* Menu: - -* Write configure.in:: Write configure.in. -* Write Makefile.am:: Write Makefile.am. -* Write acconfig.h:: Write acconfig.h. -* Generate files:: Generate files. -* Getting Started Example:: Example. - - -File: configure.info, Node: Write configure.in, Next: Write Makefile.am, Up: Getting Started - -2.1 Write configure.in -====================== - -You must first write the file 'configure.in'. This is an autoconf input -file, and the autoconf manual describes in detail what this file should -look like. - - You will write tests in your 'configure.in' file to check for -conditions that may change from one system to another, such as the -presence of particular header files or functions. - - For example, not all systems support the 'gettimeofday' function. If -you want to use the 'gettimeofday' function when it is available, and to -use some other function when it is not, you would check for this by -putting 'AC_CHECK_FUNCS(gettimeofday)' in 'configure.in'. - - When the configure script is run at build time, this will arrange to -define the preprocessor macro 'HAVE_GETTIMEOFDAY' to the value 1 if the -'gettimeofday' function is available, and to not define the macro at all -if the function is not available. Your code can then use '#ifdef' to -test whether it is safe to call 'gettimeofday'. - - If you have an existing body of code, the 'autoscan' program may help -identify potential portability problems, and hence configure tests that -you will want to use. *Note (autoconf)Invoking autoscan::. - - Another handy tool for an existing body of code is 'ifnames'. This -will show you all the preprocessor conditionals that the code already -uses. *Note (autoconf)Invoking ifnames::. - - Besides the portability tests which are specific to your particular -package, every 'configure.in' file should contain the following macros. - -'AC_INIT' - This macro takes a single argument, which is the name of a file in - your package. For example, 'AC_INIT(foo.c)'. - -'AC_PREREQ(VERSION)' - This macro is optional. It may be used to indicate the version of - 'autoconf' that you are using. This will prevent users from - running an earlier version of 'autoconf' and perhaps getting an - invalid 'configure' script. For example, 'AC_PREREQ(2.12)'. - -'AM_INIT_AUTOMAKE' - This macro takes two arguments: the name of the package, and a - version number. For example, 'AM_INIT_AUTOMAKE(foo, 1.0)'. (This - macro is not needed if you are not using automake). - -'AM_CONFIG_HEADER' - This macro names the header file which will hold the preprocessor - macro definitions at run time. Normally this should be 'config.h'. - Your sources would then use '#include "config.h"' to include it. - - This macro may optionally name the input file for that header file; - by default, this is 'config.h.in', but that file name works poorly - on DOS filesystems. Therefore, it is often better to name it - explicitly as 'config.in'. - - This is what you should normally put in 'configure.in': - AM_CONFIG_HEADER(config.h:config.in) - - (If you are not using automake, use 'AC_CONFIG_HEADER' rather than - 'AM_CONFIG_HEADER'). - -'AM_MAINTAINER_MODE' - This macro always appears in Cygnus configure scripts. Other - programs may or may not use it. - - If this macro is used, the '--enable-maintainer-mode' option is - required to enable automatic rebuilding of generated files used by - the configure system. This of course requires that developers be - aware of, and use, that option. - - If this macro is not used, then the generated files will always be - rebuilt automatically. This will cause problems if the wrong - versions of autoconf, automake, or others are in the builder's - 'PATH'. - - (If you are not using automake, you do not need to use this macro). - -'AC_EXEEXT' - Either this macro or 'AM_EXEEXT' always appears in Cygnus configure - files. Other programs may or may not use one of them. - - This macro looks for the executable suffix used on the host system. - On Unix systems, this is the empty string. On Windows systems, - this is '.exe'. This macro directs automake to use the executable - suffix as appropriate when creating programs. This macro does not - take any arguments. - - The 'AC_EXEEXT' form is new, and is part of a Cygnus patch to - autoconf to support compiling with Visual C++. Older programs use - 'AM_EXEEXT' instead. - - (Programs which do not use automake use neither 'AC_EXEEXT' nor - 'AM_EXEEXT'). - -'AC_PROG_CC' - If you are writing C code, you will normally want to use this - macro. It locates the C compiler to use. It does not take any - arguments. - - However, if this 'configure.in' file is for a library which is to - be compiled by a cross compiler which may not fully work, then you - will not want to use 'AC_PROG_CC'. Instead, you will want to use a - variant which does not call the macro 'AC_PROG_CC_WORKS'. Examples - can be found in various 'configure.in' files for libraries that are - compiled with cross compilers, such as libiberty or libgloss. This - is essentially a bug in autoconf, and there will probably be a - better workaround at some point. - -'AC_PROG_CXX' - If you are writing C++ code, you will want to use this macro. It - locates the C++ compiler to use. It does not take any arguments. - The same cross compiler comments apply as for 'AC_PROG_CC'. - -'AM_PROG_LIBTOOL' - If you want to build libraries, and you want to permit them to be - shared, or you want to link against libraries which were built - using libtool, then you will need this macro. This macro is - required in order to use libtool. - - By default, this will cause all libraries to be built as shared - libraries. To prevent this-to change the default-use - 'AM_DISABLE_SHARED' before 'AM_PROG_LIBTOOL'. The configure - options '--enable-shared' and '--disable-shared' may be used to - override the default at build time. - -'AC_DEFINE(_GNU_SOURCE)' - GNU packages should normally include this line before any other - feature tests. This defines the macro '_GNU_SOURCE' when - compiling, which directs the libc header files to provide the - standard GNU system interfaces including all GNU extensions. If - this macro is not defined, certain GNU extensions may not be - available. - -'AC_OUTPUT' - This macro takes a list of file names which the configure process - should produce. This is normally a list of one or more 'Makefile' - files in different directories. If your package lives entirely in - a single directory, you would use simply 'AC_OUTPUT(Makefile)'. If - you also have, for example, a 'lib' subdirectory, you would use - 'AC_OUTPUT(Makefile lib/Makefile)'. - - If you want to use locally defined macros in your 'configure.in' -file, then you will need to write a 'acinclude.m4' file which defines -them (if not using automake, this file is called 'aclocal.m4'). -Alternatively, you can put separate macros in an 'm4' subdirectory, and -put 'ACLOCAL_AMFLAGS = -I m4' in your 'Makefile.am' file so that the -'aclocal' program will be able to find them. - - The different macro prefixes indicate which tool defines the macro. -Macros which start with 'AC_' are part of autoconf. Macros which start -with 'AM_' are provided by automake or libtool. - - -File: configure.info, Node: Write Makefile.am, Next: Write acconfig.h, Prev: Write configure.in, Up: Getting Started - -2.2 Write Makefile.am -===================== - -You must write the file 'Makefile.am'. This is an automake input file, -and the automake manual describes in detail what this file should look -like. - - The automake commands in 'Makefile.am' mostly look like variable -assignments in a 'Makefile'. automake recognizes special variable -names, and automatically add make rules to the output as needed. - - There will be one 'Makefile.am' file for each directory in your -package. For each directory with subdirectories, the 'Makefile.am' file -should contain the line - SUBDIRS = DIR DIR ... -where each DIR is the name of a subdirectory. - - For each 'Makefile.am', there should be a corresponding 'Makefile' in -the 'AC_OUTPUT' macro in 'configure.in'. - - Every 'Makefile.am' written at Cygnus should contain the line - AUTOMAKE_OPTIONS = cygnus -This puts automake into Cygnus mode. See the automake manual for -details. - - You may to include the version number of 'automake' that you are -using on the 'AUTOMAKE_OPTIONS' line. For example, - AUTOMAKE_OPTIONS = cygnus 1.3 -This will prevent users from running an earlier version of 'automake' -and perhaps getting an invalid 'Makefile.in'. - - If your package builds a program, then in the directory where that -program is built you will normally want a line like - bin_PROGRAMS = PROGRAM -where PROGRAM is the name of the program. You will then want a line -like - PROGRAM_SOURCES = FILE FILE ... -where each FILE is the name of a source file to link into the program -(e.g., 'foo.c'). - - If your package builds a library, and you do not want the library to -ever be built as a shared library, then in the directory where that -library is built you will normally want a line like - lib_LIBRARIES = libNAME.a -where 'libNAME.a' is the name of the library. You will then want a line -like - libNAME_a_SOURCES = FILE FILE ... -where each FILE is the name of a source file to add to the library. - - If your package builds a library, and you want to permit building the -library as a shared library, then in the directory where that library is -built you will normally want a line like - lib_LTLIBRARIES = libNAME.la - The use of 'LTLIBRARIES', and the '.la' extension, indicate a library -to be built using libtool. As usual, you will then want a line like - libNAME_la_SOURCES = FILE FILE ... - - The strings 'bin' and 'lib' that appear above in 'bin_PROGRAMS' and -'lib_LIBRARIES' are not arbitrary. They refer to particular -directories, which may be set by the '--bindir' and '--libdir' options -to 'configure'. If those options are not used, the default values are -based on the '--prefix' or '--exec-prefix' options to 'configure'. It -is possible to use other names if the program or library should be -installed in some other directory. - - The 'Makefile.am' file may also contain almost anything that may -appear in a normal 'Makefile'. automake also supports many other -special variables, as well as conditionals. - - See the automake manual for more information. - - -File: configure.info, Node: Write acconfig.h, Next: Generate files, Prev: Write Makefile.am, Up: Getting Started - -2.3 Write acconfig.h -==================== - -If you are generating a portability header file, (i.e., you are using -'AM_CONFIG_HEADER' in 'configure.in'), then you will have to write a -'acconfig.h' file. It will have to contain the following lines. - - /* Name of package. */ - #undef PACKAGE - - /* Version of package. */ - #undef VERSION - - This requirement is really a bug in the system, and the requirement -may be eliminated at some later date. - - The 'acconfig.h' file will also similar comment and '#undef' lines -for any unusual macros in the 'configure.in' file, including any macro -which appears in a 'AC_DEFINE' macro. - - In particular, if you are writing a GNU package and therefore include -'AC_DEFINE(_GNU_SOURCE)' in 'configure.in' as suggested above, you will -need lines like this in 'acconfig.h': - /* Enable GNU extensions. */ - #undef _GNU_SOURCE - - Normally the 'autoheader' program will inform you of any such -requirements by printing an error message when it is run. However, if -you do anything particular odd in your 'configure.in' file, you will -have to make sure that the right entries appear in 'acconfig.h', since -otherwise the results of the tests may not be available in the -'config.h' file which your code will use. - - (Thee 'PACKAGE' and 'VERSION' lines are not required if you are not -using automake, and in that case you may not need a 'acconfig.h' file at -all). - - -File: configure.info, Node: Generate files, Next: Getting Started Example, Prev: Write acconfig.h, Up: Getting Started - -2.4 Generate files -================== - -Once you have written 'configure.in', 'Makefile.am', 'acconfig.h', and -possibly 'acinclude.m4', you must use autoconf and automake programs to -produce the first versions of the generated files. This is done by -executing the following sequence of commands. - - aclocal - autoconf - autoheader - automake - - The 'aclocal' and 'automake' commands are part of the automake -package, and the 'autoconf' and 'autoheader' commands are part of the -autoconf package. - - If you are using a 'm4' subdirectory for your macros, you will need -to use the '-I m4' option when you run 'aclocal'. - - If you are not using the Cygnus tree, use the '-a' option when -running 'automake' command in order to copy the required support files -into your source directory. - - If you are using libtool, you must build and install the libtool -package with the same '--prefix' and '--exec-prefix' options as you used -with the autoconf and automake packages. You must do this before -running any of the above commands. If you are not using the Cygnus -tree, you will need to run the 'libtoolize' program to copy the libtool -support files into your directory. - - Once you have managed to run these commands without getting any -errors, you should create a new empty directory, and run the 'configure' -script which will have been created by 'autoconf' with the -'--enable-maintainer-mode' option. This will give you a set of -Makefiles which will include rules to automatically rebuild all the -generated files. - - After doing that, whenever you have changed some of the input files -and want to regenerated the other files, go to your object directory and -run 'make'. Doing this is more reliable than trying to rebuild the -files manually, because there are complex order dependencies and it is -easy to forget something. - - -File: configure.info, Node: Getting Started Example, Prev: Generate files, Up: Getting Started - -2.5 Example -=========== - -Let's consider a trivial example. - - Suppose we want to write a simple version of 'touch'. Our program, -which we will call 'poke', will take a single file name argument, and -use the 'utime' system call to set the modification and access times of -the file to the current time. We want this program to be highly -portable. - - We'll first see what this looks like without using autoconf and -automake, and then see what it looks like with them. - -* Menu: - -* Getting Started Example 1:: First Try. -* Getting Started Example 2:: Second Try. -* Getting Started Example 3:: Third Try. -* Generate Files in Example:: Generate Files. - - -File: configure.info, Node: Getting Started Example 1, Next: Getting Started Example 2, Up: Getting Started Example - -2.5.1 First Try ---------------- - -Here is our first try at 'poke.c'. Note that we've written it without -ANSI/ISO C prototypes, since we want it to be highly portable. - - #include - #include - #include - #include - - int - main (argc, argv) - int argc; - char **argv; - { - if (argc != 2) - { - fprintf (stderr, "Usage: poke file\n"); - exit (1); - } - - if (utime (argv[1], NULL) < 0) - { - perror ("utime"); - exit (1); - } - - exit (0); - } - - We also write a simple 'Makefile'. - - CC = gcc - CFLAGS = -g -O2 - - all: poke - - poke: poke.o - $(CC) -o poke $(CFLAGS) $(LDFLAGS) poke.o - - So far, so good. - - Unfortunately, there are a few problems. - - On older Unix systems derived from BSD 4.3, the 'utime' system call -does not accept a second argument of 'NULL'. On those systems, we need -to pass a pointer to 'struct utimbuf' structure. Unfortunately, even -older systems don't define that structure; on those systems, we need to -pass an array of two 'long' values. - - The header file 'stdlib.h' was invented by ANSI C, and older systems -don't have a copy. We included it above to get a declaration of 'exit'. - - We can find some of these portability problems by running 'autoscan', -which will create a 'configure.scan' file which we can use as a -prototype for our 'configure.in' file. I won't show the output, but it -will notice the potential problems with 'utime' and 'stdlib.h'. - - In our 'Makefile', we don't provide any way to install the program. -This doesn't matter much for such a simple example, but a real program -will need an 'install' target. For that matter, we will also want a -'clean' target. - - -File: configure.info, Node: Getting Started Example 2, Next: Getting Started Example 3, Prev: Getting Started Example 1, Up: Getting Started Example - -2.5.2 Second Try ----------------- - -Here is our second try at this program. - - We modify 'poke.c' to use preprocessor macros to control what -features are available. (I've cheated a bit by using the same macro -names which autoconf will use). - - #include - - #ifdef STDC_HEADERS - #include - #endif - - #include - - #ifdef HAVE_UTIME_H - #include - #endif - - #ifndef HAVE_UTIME_NULL - - #include - - #ifndef HAVE_STRUCT_UTIMBUF - - struct utimbuf - { - long actime; - long modtime; - }; - - #endif - - static int - utime_now (file) - char *file; - { - struct utimbuf now; - - now.actime = now.modtime = time (NULL); - return utime (file, &now); - } - - #define utime(f, p) utime_now (f) - - #endif /* HAVE_UTIME_NULL */ - - int - main (argc, argv) - int argc; - char **argv; - { - if (argc != 2) - { - fprintf (stderr, "Usage: poke file\n"); - exit (1); - } - - if (utime (argv[1], NULL) < 0) - { - perror ("utime"); - exit (1); - } - - exit (0); - } - - Here is the associated 'Makefile'. We've added support for the -preprocessor flags we use. We've also added 'install' and 'clean' -targets. - - # Set this to your installation directory. - bindir = /usr/local/bin - - # Uncomment this if you have the standard ANSI/ISO C header files. - # STDC_HDRS = -DSTDC_HEADERS - - # Uncomment this if you have utime.h. - # UTIME_H = -DHAVE_UTIME_H - - # Uncomment this if utime (FILE, NULL) works on your system. - # UTIME_NULL = -DHAVE_UTIME_NULL - - # Uncomment this if struct utimbuf is defined in utime.h. - # UTIMBUF = -DHAVE_STRUCT_UTIMBUF - - CC = gcc - CFLAGS = -g -O2 - - ALL_CFLAGS = $(STDC_HDRS) $(UTIME_H) $(UTIME_NULL) $(UTIMBUF) $(CFLAGS) - - all: poke - - poke: poke.o - $(CC) -o poke $(ALL_CFLAGS) $(LDFLAGS) poke.o - - .c.o: - $(CC) -c $(ALL_CFLAGS) poke.c - - install: poke - cp poke $(bindir)/poke - - clean: - rm poke poke.o - - Some problems with this approach should be clear. - - Users who want to compile poke will have to know how 'utime' works on -their systems, so that they can uncomment the 'Makefile' correctly. - - The installation is done using 'cp', but many systems have an -'install' program which may be used, and which supports optional -features such as stripping debugging information out of the installed -binary. - - The use of 'Makefile' variables like 'CC', 'CFLAGS' and 'LDFLAGS' -follows the requirements of the GNU standards. This is convenient for -all packages, since it reduces surprises for users. However, it is easy -to get the details wrong, and wind up with a slightly nonstandard -distribution. - - -File: configure.info, Node: Getting Started Example 3, Next: Generate Files in Example, Prev: Getting Started Example 2, Up: Getting Started Example - -2.5.3 Third Try ---------------- - -For our third try at this program, we will write a 'configure.in' script -to discover the configuration features on the host system, rather than -requiring the user to edit the 'Makefile'. We will also write a -'Makefile.am' rather than a 'Makefile'. - - The only change to 'poke.c' is to add a line at the start of the -file: - #include "config.h" - - The new 'configure.in' file is as follows. - - AC_INIT(poke.c) - AM_INIT_AUTOMAKE(poke, 1.0) - AM_CONFIG_HEADER(config.h:config.in) - AC_PROG_CC - AC_HEADER_STDC - AC_CHECK_HEADERS(utime.h) - AC_EGREP_HEADER(utimbuf, utime.h, AC_DEFINE(HAVE_STRUCT_UTIMBUF)) - AC_FUNC_UTIME_NULL - AC_OUTPUT(Makefile) - - The first four macros in this file, and the last one, were described -above; see *note Write configure.in::. If we omit these macros, then -when we run 'automake' we will get a reminder that we need them. - - The other macros are standard autoconf macros. - -'AC_HEADER_STDC' - Check for standard C headers. -'AC_CHECK_HEADERS' - Check whether a particular header file exists. -'AC_EGREP_HEADER' - Check for a particular string in a particular header file, in this - case checking for 'utimbuf' in 'utime.h'. -'AC_FUNC_UTIME_NULL' - Check whether 'utime' accepts a NULL second argument to set the - file change time to the current time. - - See the autoconf manual for a more complete description. - - The new 'Makefile.am' file is as follows. Note how simple this is -compared to our earlier 'Makefile'. - - bin_PROGRAMS = poke - - poke_SOURCES = poke.c - - This means that we should build a single program name 'poke'. It -should be installed in the binary directory, which we called 'bindir' -earlier. The program 'poke' is built from the source file 'poke.c'. - - We must also write a 'acconfig.h' file. Besides 'PACKAGE' and -'VERSION', which must be mentioned for all packages which use automake, -we must include 'HAVE_STRUCT_UTIMBUF', since we mentioned it in an -'AC_DEFINE'. - - /* Name of package. */ - #undef PACKAGE - - /* Version of package. */ - #undef VERSION - - /* Whether utime.h defines struct utimbuf. */ - #undef HAVE_STRUCT_UTIMBUF - - -File: configure.info, Node: Generate Files in Example, Prev: Getting Started Example 3, Up: Getting Started Example - -2.5.4 Generate Files --------------------- - -We must now generate the other files, using the following commands. - - aclocal - autoconf - autoheader - automake - - When we run 'autoheader', it will remind us of any macros we forgot -to add to 'acconfig.h'. - - When we run 'automake', it will want to add some files to our -distribution. It will add them automatically if we use the -'--add-missing' option. - - By default, 'automake' will run in GNU mode, which means that it will -want us to create certain additional files; as of this writing, it will -want 'NEWS', 'README', 'AUTHORS', and 'ChangeLog', all of which are -files which should appear in a standard GNU distribution. We can either -add those files, or run 'automake' with the '--foreign' option. - - Running these tools will generate the following files, all of which -are described in the next chapter. - - * 'aclocal.m4' - * 'configure' - * 'config.in' - * 'Makefile.in' - * 'stamp-h.in' - - -File: configure.info, Node: Files, Next: Configuration Names, Prev: Getting Started, Up: Top - -3 Files -******* - -As was seen in the previous chapter, the GNU configure and build system -uses a number of different files. The developer must write a few files. -The others are generated by various tools. - - The system is rather flexible, and can be used in many different -ways. In describing the files that it uses, I will describe the common -case, and mention some other cases that may arise. - -* Menu: - -* Developer Files:: Developer Files. -* Build Files:: Build Files. -* Support Files:: Support Files. - - -File: configure.info, Node: Developer Files, Next: Build Files, Up: Files - -3.1 Developer Files -=================== - -This section describes the files written or generated by the developer -of a package. - -* Menu: - -* Developer Files Picture:: Developer Files Picture. -* Written Developer Files:: Written Developer Files. -* Generated Developer Files:: Generated Developer Files. - - -File: configure.info, Node: Developer Files Picture, Next: Written Developer Files, Up: Developer Files - -3.1.1 Developer Files Picture ------------------------------ - -Here is a picture of the files which are written by the developer, the -generated files which would be included with a complete source -distribution, and the tools which create those files. The file names -are plain text and the tool names are enclosed by '*' characters (e.g., -'autoheader' is the name of a tool, not the name of a file). - - acconfig.h configure.in Makefile.am - | | | - | --------------+---------------------- | - | | | | | - v v | acinclude.m4 | | - *autoheader* | | v v - | | v --->*automake* - v |--->*aclocal* | | - config.in | | | v - | v | Makefile.in - | aclocal.m4--- - | | - v v - *autoconf* - | - v - configure - -File: configure.info, Node: Written Developer Files, Next: Generated Developer Files, Prev: Developer Files Picture, Up: Developer Files - -3.1.2 Written Developer Files ------------------------------ - -The following files would be written by the developer. - -'configure.in' - This is the configuration script. This script contains invocations - of autoconf macros. It may also contain ordinary shell script - code. This file will contain feature tests for portability issues. - The last thing in the file will normally be an 'AC_OUTPUT' macro - listing which files to create when the builder runs the configure - script. This file is always required when using the GNU configure - system. *Note Write configure.in::. - -'Makefile.am' - This is the automake input file. It describes how the code should - be built. It consists of definitions of automake variables. It - may also contain ordinary Makefile targets. This file is only - needed when using automake (newer tools normally use automake, but - there are still older tools which have not been converted, in which - the developer writes 'Makefile.in' directly). *Note Write - Makefile.am::. - -'acconfig.h' - When the configure script creates a portability header file, by - using 'AM_CONFIG_HEADER' (or, if not using automake, - 'AC_CONFIG_HEADER'), this file is used to describe macros which are - not recognized by the 'autoheader' command. This is normally a - fairly uninteresting file, consisting of a collection of '#undef' - lines with comments. Normally any call to 'AC_DEFINE' in - 'configure.in' will require a line in this file. *Note Write - acconfig.h::. - -'acinclude.m4' - This file is not always required. It defines local autoconf - macros. These macros may then be used in 'configure.in'. If you - don't need any local autoconf macros, then you don't need this file - at all. In fact, in general, you never need local autoconf macros, - since you can put everything in 'configure.in', but sometimes a - local macro is convenient. - - Newer tools may omit 'acinclude.m4', and instead use a - subdirectory, typically named 'm4', and define 'ACLOCAL_AMFLAGS = - -I m4' in 'Makefile.am' to force 'aclocal' to look there for macro - definitions. The macro definitions are then placed in separate - files in that directory. - - The 'acinclude.m4' file is only used when using automake; in older - tools, the developer writes 'aclocal.m4' directly, if it is needed. - - -File: configure.info, Node: Generated Developer Files, Prev: Written Developer Files, Up: Developer Files - -3.1.3 Generated Developer Files -------------------------------- - -The following files would be generated by the developer. - - When using automake, these files are normally not generated manually -after the first time. Instead, the generated 'Makefile' contains rules -to automatically rebuild the files as required. When -'AM_MAINTAINER_MODE' is used in 'configure.in' (the normal case in -Cygnus code), the automatic rebuilding rules will only be defined if you -configure using the '--enable-maintainer-mode' option. - - When using automatic rebuilding, it is important to ensure that all -the various tools have been built and installed on your 'PATH'. Using -automatic rebuilding is highly recommended, so much so that I'm not -going to explain what you have to do if you don't use it. - -'configure' - This is the configure script which will be run when building the - package. This is generated by 'autoconf' from 'configure.in' and - 'aclocal.m4'. This is a shell script. - -'Makefile.in' - This is the file which the configure script will turn into the - 'Makefile' at build time. This file is generated by 'automake' - from 'Makefile.am'. If you aren't using automake, you must write - this file yourself. This file is pretty much a normal 'Makefile', - with some configure substitutions for certain variables. - -'aclocal.m4' - This file is created by the 'aclocal' program, based on the - contents of 'configure.in' and 'acinclude.m4' (or, as noted in the - description of 'acinclude.m4' above, on the contents of an 'm4' - subdirectory). This file contains definitions of autoconf macros - which 'autoconf' will use when generating the file 'configure'. - These autoconf macros may be defined by you in 'acinclude.m4' or - they may be defined by other packages such as automake, libtool or - gettext. If you aren't using automake, you will normally write - this file yourself; in that case, if 'configure.in' uses only - standard autoconf macros, this file will not be needed at all. - -'config.in' - This file is created by 'autoheader' based on 'acconfig.h' and - 'configure.in'. At build time, the configure script will define - some of the macros in it to create 'config.h', which may then be - included by your program. This permits your C code to use - preprocessor conditionals to change its behaviour based on the - characteristics of the host system. This file may also be called - 'config.h.in'. - -'stamp.h-in' - This rather uninteresting file, which I omitted from the picture, - is generated by 'automake'. It always contains the string - 'timestamp'. It is used as a timestamp file indicating whether - 'config.in' is up to date. Using a timestamp file means that - 'config.in' can be marked as up to date without actually changing - its modification time. This is useful since 'config.in' depends - upon 'configure.in', but it is easy to change 'configure.in' in a - way which does not affect 'config.in'. - - -File: configure.info, Node: Build Files, Next: Support Files, Prev: Developer Files, Up: Files - -3.2 Build Files -=============== - -This section describes the files which are created at configure and -build time. These are the files which somebody who builds the package -will see. - - Of course, the developer will also build the package. The -distinction between developer files and build files is not that the -developer does not see the build files, but that somebody who only -builds the package does not have to worry about the developer files. - -* Menu: - -* Build Files Picture:: Build Files Picture. -* Build Files Description:: Build Files Description. - - -File: configure.info, Node: Build Files Picture, Next: Build Files Description, Up: Build Files - -3.2.1 Build Files Picture -------------------------- - -Here is a picture of the files which will be created at build time. -'config.status' is both a created file and a shell script which is run -to create other files, and the picture attempts to show that. - - config.in *configure* Makefile.in - | | | - | v | - | config.status | - | | | - *config.status*<======+==========>*config.status* - | | - v v - config.h Makefile - -File: configure.info, Node: Build Files Description, Prev: Build Files Picture, Up: Build Files - -3.2.2 Build Files Description ------------------------------ - -This is a description of the files which are created at build time. - -'config.status' - The first step in building a package is to run the 'configure' - script. The 'configure' script will create the file - 'config.status', which is itself a shell script. When you first - run 'configure', it will automatically run 'config.status'. An - 'Makefile' derived from an automake generated 'Makefile.in' will - contain rules to automatically run 'config.status' again when - necessary to recreate certain files if their inputs change. - -'Makefile' - This is the file which make will read to build the program. The - 'config.status' script will transform 'Makefile.in' into - 'Makefile'. - -'config.h' - This file defines C preprocessor macros which C code can use to - adjust its behaviour on different systems. The 'config.status' - script will transform 'config.in' into 'config.h'. - -'config.cache' - This file did not fit neatly into the picture, and I omitted it. - It is used by the 'configure' script to cache results between runs. - This can be an important speedup. If you modify 'configure.in' in - such a way that the results of old tests should change (perhaps you - have added a new library to 'LDFLAGS'), then you will have to - remove 'config.cache' to force the tests to be rerun. - - The autoconf manual explains how to set up a site specific cache - file. This can speed up running 'configure' scripts on your - system. - -'stamp.h' - This file, which I omitted from the picture, is similar to - 'stamp-h.in'. It is used as a timestamp file indicating whether - 'config.h' is up to date. This is useful since 'config.h' depends - upon 'config.status', but it is easy for 'config.status' to change - in a way which does not affect 'config.h'. - - -File: configure.info, Node: Support Files, Prev: Build Files, Up: Files - -3.3 Support Files -================= - -The GNU configure and build system requires several support files to be -included with your distribution. You do not normally need to concern -yourself with these. If you are using the Cygnus tree, most are already -present. Otherwise, they will be installed with your source by -'automake' (with the '--add-missing' option) and 'libtoolize'. - - You don't have to put the support files in the top level directory. -You can put them in a subdirectory, and use the 'AC_CONFIG_AUX_DIR' -macro in 'configure.in' to tell 'automake' and the 'configure' script -where they are. - - In this section, I describe the support files, so that you can know -what they are and why they are there. - -'ABOUT-NLS' - Added by automake if you are using gettext. This is a - documentation file about the gettext project. -'ansi2knr.c' - Used by an automake generated 'Makefile' if you put 'ansi2knr' in - 'AUTOMAKE_OPTIONS' in 'Makefile.am'. This permits compiling ANSI C - code with a K&R C compiler. -'ansi2knr.1' - The man page which goes with 'ansi2knr.c'. -'config.guess' - A shell script which determines the configuration name for the - system on which it is run. -'config.sub' - A shell script which canonicalizes a configuration name entered by - a user. -'elisp-comp' - Used to compile Emacs LISP files. -'install-sh' - A shell script which installs a program. This is used if the - configure script can not find an install binary. -'ltconfig' - Used by libtool. This is a shell script which configures libtool - for the particular system on which it is used. -'ltmain.sh' - Used by libtool. This is the actual libtool script which is used, - after it is configured by 'ltconfig' to build a library. -'mdate-sh' - A shell script used by an automake generated 'Makefile' to pretty - print the modification time of a file. This is used to maintain - version numbers for texinfo files. -'missing' - A shell script used if some tool is missing entirely. This is used - by an automake generated 'Makefile' to avoid certain sorts of - timestamp problems. -'mkinstalldirs' - A shell script which creates a directory, including all parent - directories. This is used by an automake generated 'Makefile' - during installation. -'texinfo.tex' - Required if you have any texinfo files. This is used when - converting Texinfo files into DVI using 'texi2dvi' and TeX. -'ylwrap' - A shell script used by an automake generated 'Makefile' to run - programs like 'bison', 'yacc', 'flex', and 'lex'. These programs - default to producing output files with a fixed name, and the - 'ylwrap' script runs them in a subdirectory to avoid file name - conflicts when using a parallel make program. - - -File: configure.info, Node: Configuration Names, Next: Cross Compilation Tools, Prev: Files, Up: Top - -4 Configuration Names -********************* - -The GNU configure system names all systems using a "configuration name". -All such names used to be triplets (they may now contain four parts in -certain cases), and the term "configuration triplet" is still seen. - -* Menu: - -* Configuration Name Definition:: Configuration Name Definition. -* Using Configuration Names:: Using Configuration Names. - - -File: configure.info, Node: Configuration Name Definition, Next: Using Configuration Names, Up: Configuration Names - -4.1 Configuration Name Definition -================================= - -This is a string of the form CPU-MANUFACTURER-OPERATING_SYSTEM. In some -cases, this is extended to a four part form: -CPU-MANUFACTURER-KERNEL-OPERATING_SYSTEM. - - When using a configuration name in a configure option, it is normally -not necessary to specify an entire name. In particular, the -MANUFACTURER field is often omitted, leading to strings such as -'i386-linux' or 'sparc-sunos'. The shell script 'config.sub' will -translate these shortened strings into the canonical form. autoconf -will arrange for 'config.sub' to be run automatically when it is needed. - - The fields of a configuration name are as follows: - -CPU - The type of processor. This is typically something like 'i386' or - 'sparc'. More specific variants are used as well, such as 'mipsel' - to indicate a little endian MIPS processor. -MANUFACTURER - A somewhat freeform field which indicates the manufacturer of the - system. This is often simply 'unknown'. Other common strings are - 'pc' for an IBM PC compatible system, or the name of a workstation - vendor, such as 'sun'. -OPERATING_SYSTEM - The name of the operating system which is run on the system. This - will be something like 'solaris2.5' or 'irix6.3'. There is no - particular restriction on the version number, and strings like - 'aix4.1.4.0' are seen. For an embedded system, which has no - operating system, this field normally indicates the type of object - file format, such as 'elf' or 'coff'. -KERNEL - This is used mainly for GNU/Linux. A typical GNU/Linux - configuration name is 'i586-pc-linux-gnulibc1'. In this case the - kernel, 'linux', is separated from the operating system, - 'gnulibc1'. - - The shell script 'config.guess' will normally print the correct -configuration name for the system on which it is run. It does by -running 'uname' and by examining other characteristics of the system. - - Because 'config.guess' can normally determine the configuration name -for a machine, it is normally only necessary to specify a configuration -name when building a cross-compiler or when building using a -cross-compiler. - - -File: configure.info, Node: Using Configuration Names, Prev: Configuration Name Definition, Up: Configuration Names - -4.2 Using Configuration Names -============================= - -A configure script will sometimes have to make a decision based on a -configuration name. You will need to do this if you have to compile -code differently based on something which can not be tested using a -standard autoconf feature test. - - It is normally better to test for particular features, rather than to -test for a particular system. This is because as Unix evolves, -different systems copy features from one another. Even if you need to -determine whether the feature is supported based on a configuration -name, you should define a macro which describes the feature, rather than -defining a macro which describes the particular system you are on. - - Testing for a particular system is normally done using a case -statement in 'configure.in'. The case statement might look something -like the following, assuming that 'host' is a shell variable holding a -canonical configuration name (which will be the case if 'configure.in' -uses the 'AC_CANONICAL_HOST' or 'AC_CANONICAL_SYSTEM' macro). - - case "${host}" in - i[3-7]86-*-linux-gnu*) do something ;; - sparc*-sun-solaris2.[56789]*) do something ;; - sparc*-sun-solaris*) do something ;; - mips*-*-elf*) do something ;; - esac - - It is particularly important to use '*' after the operating system -field, in order to match the version number which will be generated by -'config.guess'. - - In most cases you must be careful to match a range of processor -types. For most processor families, a trailing '*' suffices, as in -'mips*' above. For the i386 family, something along the lines of -'i[3-7]86' suffices at present. For the m68k family, you will need -something like 'm68*'. Of course, if you do not need to match on the -processor, it is simpler to just replace the entire field by a '*', as -in '*-*-irix*'. - - -File: configure.info, Node: Cross Compilation Tools, Next: Canadian Cross, Prev: Configuration Names, Up: Top - -5 Cross Compilation Tools -************************* - -The GNU configure and build system can be used to build "cross -compilation" tools. A cross compilation tool is a tool which runs on -one system and produces code which runs on another system. - -* Menu: - -* Cross Compilation Concepts:: Cross Compilation Concepts. -* Host and Target:: Host and Target. -* Using the Host Type:: Using the Host Type. -* Specifying the Target:: Specifying the Target. -* Using the Target Type:: Using the Target Type. -* Cross Tools in the Cygnus Tree:: Cross Tools in the Cygnus Tree - - -File: configure.info, Node: Cross Compilation Concepts, Next: Host and Target, Up: Cross Compilation Tools - -5.1 Cross Compilation Concepts -============================== - -A compiler which produces programs which run on a different system is a -cross compilation compiler, or simply a "cross compiler". Similarly, we -speak of cross assemblers, cross linkers, etc. - - In the normal case, a compiler produces code which runs on the same -system as the one on which the compiler runs. When it is necessary to -distinguish this case from the cross compilation case, such a compiler -is called a "native compiler". Similarly, we speak of native -assemblers, etc. - - Although the debugger is not strictly speaking a compilation tool, it -is nevertheless meaningful to speak of a cross debugger: a debugger -which is used to debug code which runs on another system. Everything -that is said below about configuring cross compilation tools applies to -the debugger as well. - - -File: configure.info, Node: Host and Target, Next: Using the Host Type, Prev: Cross Compilation Concepts, Up: Cross Compilation Tools - -5.2 Host and Target -=================== - -When building cross compilation tools, there are two different systems -involved: the system on which the tools will run, and the system for -which the tools generate code. - - The system on which the tools will run is called the "host" system. - - The system for which the tools generate code is called the "target" -system. - - For example, suppose you have a compiler which runs on a GNU/Linux -system and generates ELF programs for a MIPS embedded system. In this -case the GNU/Linux system is the host, and the MIPS ELF system is the -target. Such a compiler could be called a GNU/Linux cross MIPS ELF -compiler, or, equivalently, a 'i386-linux-gnu' cross 'mips-elf' -compiler. - - Naturally, most programs are not cross compilation tools. For those -programs, it does not make sense to speak of a target. It only makes -sense to speak of a target for tools like 'gcc' or the 'binutils' which -actually produce running code. For example, it does not make sense to -speak of the target of a tool like 'bison' or 'make'. - - Most cross compilation tools can also serve as native tools. For a -native compilation tool, it is still meaningful to speak of a target. -For a native tool, the target is the same as the host. For example, for -a GNU/Linux native compiler, the host is GNU/Linux, and the target is -also GNU/Linux. - - -File: configure.info, Node: Using the Host Type, Next: Specifying the Target, Prev: Host and Target, Up: Cross Compilation Tools - -5.3 Using the Host Type -======================= - -In almost all cases the host system is the system on which you run the -'configure' script, and on which you build the tools (for the case when -they differ, *note Canadian Cross::). - - If your configure script needs to know the configuration name of the -host system, and the package is not a cross compilation tool and -therefore does not have a target, put 'AC_CANONICAL_HOST' in -'configure.in'. This macro will arrange to define a few shell variables -when the 'configure' script is run. - -'host' - The canonical configuration name of the host. This will normally - be determined by running the 'config.guess' shell script, although - the user is permitted to override this by using an explicit - '--host' option. -'host_alias' - In the unusual case that the user used an explicit '--host' option, - this will be the argument to '--host'. In the normal case, this - will be the same as the 'host' variable. -'host_cpu' -'host_vendor' -'host_os' - The first three parts of the canonical configuration name. - - The shell variables may be used by putting shell code in -'configure.in'. For an example, see *note Using Configuration Names::. - - -File: configure.info, Node: Specifying the Target, Next: Using the Target Type, Prev: Using the Host Type, Up: Cross Compilation Tools - -5.4 Specifying the Target -========================= - -By default, the 'configure' script will assume that the target is the -same as the host. This is the more common case; for example, it leads -to a native compiler rather than a cross compiler. - - If you want to build a cross compilation tool, you must specify the -target explicitly by using the '--target' option when you run -'configure'. The argument to '--target' is the configuration name of -the system for which you wish to generate code. *Note Configuration -Names::. - - For example, to build tools which generate code for a MIPS ELF -embedded system, you would use '--target mips-elf'. - - -File: configure.info, Node: Using the Target Type, Next: Cross Tools in the Cygnus Tree, Prev: Specifying the Target, Up: Cross Compilation Tools - -5.5 Using the Target Type -========================= - -When writing 'configure.in' for a cross compilation tool, you will need -to use information about the target. To do this, put -'AC_CANONICAL_SYSTEM' in 'configure.in'. - - 'AC_CANONICAL_SYSTEM' will look for a '--target' option and -canonicalize it using the 'config.sub' shell script. It will also run -'AC_CANONICAL_HOST' (*note Using the Host Type::). - - The target type will be recorded in the following shell variables. -Note that the host versions of these variables will also be defined by -'AC_CANONICAL_HOST'. - -'target' - The canonical configuration name of the target. -'target_alias' - The argument to the '--target' option. If the user did not specify - a '--target' option, this will be the same as 'host_alias'. -'target_cpu' -'target_vendor' -'target_os' - The first three parts of the canonical target configuration name. - - Note that if 'host' and 'target' are the same string, you can assume -a native configuration. If they are different, you can assume a cross -configuration. - - It is arguably possible for 'host' and 'target' to represent the same -system, but for the strings to not be identical. For example, if -'config.guess' returns 'sparc-sun-sunos4.1.4', and somebody configures -with '--target sparc-sun-sunos4.1', then the slight differences between -the two versions of SunOS may be unimportant for your tool. However, in -the general case it can be quite difficult to determine whether the -differences between two configuration names are significant or not. -Therefore, by convention, if the user specifies a '--target' option -without specifying a '--host' option, it is assumed that the user wants -to configure a cross compilation tool. - - The variables 'target' and 'target_alias' should be handled -differently. - - In general, whenever the user may actually see a string, -'target_alias' should be used. This includes anything which may appear -in the file system, such as a directory name or part of a tool name. It -also includes any tool output, unless it is clearly labelled as the -canonical target configuration name. This permits the user to use the -'--target' option to specify how the tool will appear to the outside -world. - - On the other hand, when checking for characteristics of the target -system, 'target' should be used. This is because a wide variety of -'--target' options may map into the same canonical configuration name. -You should not attempt to duplicate the canonicalization done by -'config.sub' in your own code. - - By convention, cross tools are installed with a prefix of the -argument used with the '--target' option, also known as 'target_alias' -(*note Using the Target Type::). If the user does not use the -'--target' option, and thus is building a native tool, no prefix is -used. - - For example, if gcc is configured with '--target mips-elf', then the -installed binary will be named 'mips-elf-gcc'. If gcc is configured -without a '--target' option, then the installed binary will be named -'gcc'. - - The autoconf macro 'AC_ARG_PROGRAM' will handle this for you. If you -are using automake, no more need be done; the programs will -automatically be installed with the correct prefixes. Otherwise, see -the autoconf documentation for 'AC_ARG_PROGRAM'. - - -File: configure.info, Node: Cross Tools in the Cygnus Tree, Prev: Using the Target Type, Up: Cross Compilation Tools - -5.6 Cross Tools in the Cygnus Tree -================================== - -The Cygnus tree is used for various packages including gdb, the GNU -binutils, and egcs. It is also, of course, used for Cygnus releases. - - In the Cygnus tree, the top level 'configure' script uses the old -Cygnus configure system, not autoconf. The top level 'Makefile.in' is -written to build packages based on what is in the source tree, and -supports building a large number of tools in a single 'configure'/'make' -step. - - The Cygnus tree may be configured with a '--target' option. The -'--target' option applies recursively to every subdirectory, and permits -building an entire set of cross tools at once. - -* Menu: - -* Host and Target Libraries:: Host and Target Libraries. -* Target Library Configure Scripts:: Target Library Configure Scripts. -* Make Targets in Cygnus Tree:: Make Targets in Cygnus Tree. -* Target libiberty:: Target libiberty - - -File: configure.info, Node: Host and Target Libraries, Next: Target Library Configure Scripts, Up: Cross Tools in the Cygnus Tree - -5.6.1 Host and Target Libraries -------------------------------- - -The Cygnus tree distinguishes host libraries from target libraries. - - Host libraries are built with the compiler used to build the programs -which run on the host, which is called the host compiler. This includes -libraries such as 'bfd' and 'tcl'. These libraries are built with the -host compiler, and are linked into programs like the binutils or gcc -which run on the host. - - Target libraries are built with the target compiler. If gcc is -present in the source tree, then the target compiler is the gcc that is -built using the host compiler. Target libraries are libraries such as -'newlib' and 'libstdc++'. These libraries are not linked into the host -programs, but are instead made available for use with programs built -with the target compiler. - - For the rest of this section, assume that gcc is present in the -source tree, so that it will be used to build the target libraries. - - There is a complication here. The configure process needs to know -which compiler you are going to use to build a tool; otherwise, the -feature tests will not work correctly. The Cygnus tree handles this by -not configuring the target libraries until the target compiler is built. -In order to permit everything to build using a single -'configure'/'make', the configuration of the target libraries is -actually triggered during the make step. - - When the target libraries are configured, the '--target' option is -not used. Instead, the '--host' option is used with the argument of the -'--target' option for the overall configuration. If no '--target' -option was used for the overall configuration, the '--host' option will -be passed with the output of the 'config.guess' shell script. Any -'--build' option is passed down unchanged. - - This translation of configuration options is done because since the -target libraries are compiled with the target compiler, they are being -built in order to run on the target of the overall configuration. By -the definition of host, this means that their host system is the same as -the target system of the overall configuration. - - The same process is used for both a native configuration and a cross -configuration. Even when using a native configuration, the target -libraries will be configured and built using the newly built compiler. -This is particularly important for the C++ libraries, since there is no -reason to assume that the C++ compiler used to build the host tools (if -there even is one) uses the same ABI as the g++ compiler which will be -used to build the target libraries. - - There is one difference between a native configuration and a cross -configuration. In a native configuration, the target libraries are -normally configured and built as siblings of the host tools. In a cross -configuration, the target libraries are normally built in a subdirectory -whose name is the argument to '--target'. This is mainly for historical -reasons. - - To summarize, running 'configure' in the Cygnus tree configures all -the host libraries and tools, but does not configure any of the target -libraries. Running 'make' then does the following steps: - - * Build the host libraries. - * Build the host programs, including gcc. Note that we call gcc both - a host program (since it runs on the host) and a target compiler - (since it generates code for the target). - * Using the newly built target compiler, configure the target - libraries. - * Build the target libraries. - - The steps need not be done in precisely this order, since they are -actually controlled by 'Makefile' targets. - - -File: configure.info, Node: Target Library Configure Scripts, Next: Make Targets in Cygnus Tree, Prev: Host and Target Libraries, Up: Cross Tools in the Cygnus Tree - -5.6.2 Target Library Configure Scripts --------------------------------------- - -There are a few things you must know in order to write a configure -script for a target library. This is just a quick sketch, and beginners -shouldn't worry if they don't follow everything here. - - The target libraries are configured and built using a newly built -target compiler. There may not be any startup files or libraries for -this target compiler. In fact, those files will probably be built as -part of some target library, which naturally means that they will not -exist when your target library is configured. - - This means that the configure script for a target library may not use -any test which requires doing a link. This unfortunately includes many -useful autoconf macros, such as 'AC_CHECK_FUNCS'. autoconf macros which -do a compile but not a link, such as 'AC_CHECK_HEADERS', may be used. - - This is a severe restriction, but normally not a fatal one, as target -libraries can often assume the presence of other target libraries, and -thus know which functions will be available. - - As of this writing, the autoconf macro 'AC_PROG_CC' does a link to -make sure that the compiler works. This may fail in a target library, -so target libraries must use a different set of macros to locate the -compiler. See the 'configure.in' file in a directory like 'libiberty' -or 'libgloss' for an example. - - As noted in the previous section, target libraries are sometimes -built in directories which are siblings to the host tools, and are -sometimes built in a subdirectory. The '--with-target-subdir' configure -option will be passed when the library is configured. Its value will be -an empty string if the target library is a sibling. Its value will be -the name of the subdirectory if the target library is in a subdirectory. - - If the overall build is not a native build (i.e., the overall -configure used the '--target' option), then the library will be -configured with the '--with-cross-host' option. The value of this -option will be the host system of the overall build. Recall that the -host system of the library will be the target of the overall build. If -the overall build is a native build, the '--with-cross-host' option will -not be used. - - A library which can be built both standalone and as a target library -may want to install itself into different directories depending upon the -case. When built standalone, or when built native, the library should -be installed in '$(libdir)'. When built as a target library which is -not native, the library should be installed in '$(tooldir)/lib'. The -'--with-cross-host' option may be used to distinguish these cases. - - This same test of '--with-cross-host' may be used to see whether it -is OK to use link tests in the configure script. If the -'--with-cross-host' option is not used, then the library is being built -either standalone or native, and a link should work. - - -File: configure.info, Node: Make Targets in Cygnus Tree, Next: Target libiberty, Prev: Target Library Configure Scripts, Up: Cross Tools in the Cygnus Tree - -5.6.3 Make Targets in Cygnus Tree ---------------------------------- - -The top level 'Makefile' in the Cygnus tree defines targets for every -known subdirectory. - - For every subdirectory DIR which holds a host library or program, the -'Makefile' target 'all-DIR' will build that library or program. - - There are dependencies among host tools. For example, building gcc -requires first building gas, because the gcc build process invokes the -target assembler. These dependencies are reflected in the top level -'Makefile'. - - For every subdirectory DIR which holds a target library, the -'Makefile' target 'configure-target-DIR' will configure that library. -The 'Makefile' target 'all-target-DIR' will build that library. - - Every 'configure-target-DIR' target depends upon 'all-gcc', since -gcc, the target compiler, is required to configure the tool. Every -'all-target-DIR' target depends upon the corresponding -'configure-target-DIR' target. - - There are several other targets which may be of interest for each -directory: 'install-DIR', 'clean-DIR', and 'check-DIR'. There are also -corresponding 'target' versions of these for the target libraries , such -as 'install-target-DIR'. - - -File: configure.info, Node: Target libiberty, Prev: Make Targets in Cygnus Tree, Up: Cross Tools in the Cygnus Tree - -5.6.4 Target libiberty ----------------------- - -The 'libiberty' subdirectory is currently a special case, in that it is -the only directory which is built both using the host compiler and using -the target compiler. - - This is because the files in 'libiberty' are used when building the -host tools, and they are also incorporated into the 'libstdc++' target -library as support code. - - This duality does not pose any particular difficulties. It means -that there are targets for both 'all-libiberty' and -'all-target-libiberty'. - - In a native configuration, when target libraries are not built in a -subdirectory, the same objects are normally used as both the host build -and the target build. This is normally OK, since libiberty contains -only C code, and in a native configuration the results of the host -compiler and the target compiler are normally interoperable. - - Irix 6 is again an exception here, since the SGI native compiler -defaults to using the 'O32' ABI, and gcc defaults to using the 'N32' -ABI. On Irix 6, the target libraries are built in a subdirectory even -for a native configuration, avoiding this problem. - - There are currently no other libraries built for both the host and -the target, but there is no conceptual problem with adding more. - - -File: configure.info, Node: Canadian Cross, Next: Cygnus Configure, Prev: Cross Compilation Tools, Up: Top - -6 Canadian Cross -**************** - -It is possible to use the GNU configure and build system to build a -program which will run on a system which is different from the system on -which the tools are built. In other words, it is possible to build -programs using a cross compiler. - - This is referred to as a "Canadian Cross". - -* Menu: - -* Canadian Cross Example:: Canadian Cross Example. -* Canadian Cross Concepts:: Canadian Cross Concepts. -* Build Cross Host Tools:: Build Cross Host Tools. -* Build and Host Options:: Build and Host Options. -* CCross not in Cygnus Tree:: Canadian Cross not in Cygnus Tree. -* CCross in Cygnus Tree:: Canadian Cross in Cygnus Tree. -* Supporting Canadian Cross:: Supporting Canadian Cross. - - -File: configure.info, Node: Canadian Cross Example, Next: Canadian Cross Concepts, Up: Canadian Cross - -6.1 Canadian Cross Example -========================== - -Here is an example of a Canadian Cross. - - While running on a GNU/Linux, you can build a program which will run -on a Solaris system. You would use a GNU/Linux cross Solaris compiler -to build the program. - - Of course, you could not run the resulting program on your GNU/Linux -system. You would have to copy it over to a Solaris system before you -would run it. - - Of course, you could also simply build the programs on the Solaris -system in the first place. However, perhaps the Solaris system is not -available for some reason; perhaps you actually don't have one, but you -want to build the tools for somebody else to use. Or perhaps your -GNU/Linux system is much faster than your Solaris system. - - A Canadian Cross build is most frequently used when building programs -to run on a non-Unix system, such as DOS or Windows. It may be simpler -to configure and build on a Unix system than to support the -configuration machinery on a non-Unix system. - - -File: configure.info, Node: Canadian Cross Concepts, Next: Build Cross Host Tools, Prev: Canadian Cross Example, Up: Canadian Cross - -6.2 Canadian Cross Concepts -=========================== - -When building a Canadian Cross, there are at least two different systems -involved: the system on which the tools are being built, and the system -on which the tools will run. - - The system on which the tools are being built is called the "build" -system. - - The system on which the tools will run is called the host system. - - For example, if you are building a Solaris program on a GNU/Linux -system, as in the previous section, the build system would be GNU/Linux, -and the host system would be Solaris. - - It is, of course, possible to build a cross compiler using a Canadian -Cross (i.e., build a cross compiler using a cross compiler). In this -case, the system for which the resulting cross compiler generates code -is called the target system. (For a more complete discussion of host -and target systems, *note Host and Target::). - - An example of building a cross compiler using a Canadian Cross would -be building a Windows cross MIPS ELF compiler on a GNU/Linux system. In -this case the build system would be GNU/Linux, the host system would be -Windows, and the target system would be MIPS ELF. - - The name Canadian Cross comes from the case when the build, host, and -target systems are all different. At the time that these issues were -all being hashed out, Canada had three national political parties. - - -File: configure.info, Node: Build Cross Host Tools, Next: Build and Host Options, Prev: Canadian Cross Concepts, Up: Canadian Cross - -6.3 Build Cross Host Tools -========================== - -In order to configure a program for a Canadian Cross build, you must -first build and install the set of cross tools you will use to build the -program. - - These tools will be build cross host tools. That is, they will run -on the build system, and will produce code that runs on the host system. - - It is easy to confuse the meaning of build and host here. Always -remember that the build system is where you are doing the build, and the -host system is where the resulting program will run. Therefore, you -need a build cross host compiler. - - In general, you must have a complete cross environment in order to do -the build. This normally means a cross compiler, cross assembler, and -so forth, as well as libraries and include files for the host system. - - -File: configure.info, Node: Build and Host Options, Next: CCross not in Cygnus Tree, Prev: Build Cross Host Tools, Up: Canadian Cross - -6.4 Build and Host Options -========================== - -When you run 'configure', you must use both the '--build' and '--host' -options. - - The '--build' option is used to specify the configuration name of the -build system. This can normally be the result of running the -'config.guess' shell script, and it is reasonable to use -'--build=`config.guess`'. - - The '--host' option is used to specify the configuration name of the -host system. - - As we explained earlier, 'config.guess' is used to set the default -value for the '--host' option (*note Using the Host Type::). We can now -see that since 'config.guess' returns the type of system on which it is -run, it really identifies the build system. Since the host system is -normally the same as the build system (i.e., people do not normally -build using a cross compiler), it is reasonable to use the result of -'config.guess' as the default for the host system when the '--host' -option is not used. - - It might seem that if the '--host' option were used without the -'--build' option that the configure script could run 'config.guess' to -determine the build system, and presume a Canadian Cross if the result -of 'config.guess' differed from the '--host' option. However, for -historical reasons, some configure scripts are routinely run using an -explicit '--host' option, rather than using the default from -'config.guess'. As noted earlier, it is difficult or impossible to -reliably compare configuration names (*note Using the Target Type::). -Therefore, by convention, if the '--host' option is used, but the -'--build' option is not used, then the build system defaults to the host -system. - - -File: configure.info, Node: CCross not in Cygnus Tree, Next: CCross in Cygnus Tree, Prev: Build and Host Options, Up: Canadian Cross - -6.5 Canadian Cross not in Cygnus Tree. -====================================== - -If you are not using the Cygnus tree, you must explicitly specify the -cross tools which you want to use to build the program. This is done by -setting environment variables before running the 'configure' script. - - You must normally set at least the environment variables 'CC', 'AR', -and 'RANLIB' to the cross tools which you want to use to build. - - For some programs, you must set additional cross tools as well, such -as 'AS', 'LD', or 'NM'. - - You would set these environment variables to the build cross tools -which you are going to use. - - For example, if you are building a Solaris program on a GNU/Linux -system, and your GNU/Linux cross Solaris compiler were named -'solaris-gcc', then you would set the environment variable 'CC' to -'solaris-gcc'. - - -File: configure.info, Node: CCross in Cygnus Tree, Next: Supporting Canadian Cross, Prev: CCross not in Cygnus Tree, Up: Canadian Cross - -6.6 Canadian Cross in Cygnus Tree -================================= - -This section describes configuring and building a Canadian Cross when -using the Cygnus tree. - -* Menu: - -* Standard Cygnus CCross:: Building a Normal Program. -* Cross Cygnus CCross:: Building a Cross Program. - - -File: configure.info, Node: Standard Cygnus CCross, Next: Cross Cygnus CCross, Up: CCross in Cygnus Tree - -6.6.1 Building a Normal Program -------------------------------- - -When configuring a Canadian Cross in the Cygnus tree, all the -appropriate environment variables are automatically set to 'HOST-TOOL', -where HOST is the value used for the '--host' option, and TOOL is the -name of the tool (e.g., 'gcc', 'as', etc.). These tools must be on your -'PATH'. - - Adding a prefix of HOST will give the usual name for the build cross -host tools. To see this, consider that when these cross tools were -built, they were configured to run on the build system and to produce -code for the host system. That is, they were configured with a -'--target' option that is the same as the system which we are now -calling the host. Recall that the default name for installed cross -tools uses the target system as a prefix (*note Using the Target -Type::). Since that is the system which we are now calling the host, -HOST is the right prefix to use. - - For example, if you configure with '--build=i386-linux-gnu' and -'--host=solaris', then the Cygnus tree will automatically default to -using the compiler 'solaris-gcc'. You must have previously built and -installed this compiler, probably by doing a build with no '--host' -option and with a '--target' option of 'solaris'. - - -File: configure.info, Node: Cross Cygnus CCross, Prev: Standard Cygnus CCross, Up: CCross in Cygnus Tree - -6.6.2 Building a Cross Program ------------------------------- - -There are additional considerations if you want to build a cross -compiler, rather than a native compiler, in the Cygnus tree using a -Canadian Cross. - - When you build a cross compiler using the Cygnus tree, then the -target libraries will normally be built with the newly built target -compiler (*note Host and Target Libraries::). However, this will not -work when building with a Canadian Cross. This is because the newly -built target compiler will be a program which runs on the host system, -and therefore will not be able to run on the build system. - - Therefore, when building a cross compiler with the Cygnus tree, you -must first install a set of build cross target tools. These tools will -be used when building the target libraries. - - Note that this is not a requirement of a Canadian Cross in general. -For example, it would be possible to build just the host cross target -tools on the build system, to copy the tools to the host system, and to -build the target libraries on the host system. The requirement for -build cross target tools is imposed by the Cygnus tree, which expects to -be able to build both host programs and target libraries in a single -'configure'/'make' step. Because it builds these in a single step, it -expects to be able to build the target libraries on the build system, -which means that it must use a build cross target toolchain. - - For example, suppose you want to build a Windows cross MIPS ELF -compiler on a GNU/Linux system. You must have previously installed both -a GNU/Linux cross Windows compiler and a GNU/Linux cross MIPS ELF -compiler. - - In order to build the Windows (configuration name 'i386-cygwin32') -cross MIPS ELF (configure name 'mips-elf') compiler, you might execute -the following commands (long command lines are broken across lines with -a trailing backslash as a continuation character). - - mkdir linux-x-cygwin32 - cd linux-x-cygwin32 - SRCDIR/configure --target i386-cygwin32 --prefix=INSTALLDIR \ - --exec-prefix=INSTALLDIR/H-i386-linux - make - make install - cd .. - mkdir linux-x-mips-elf - cd linux-x-mips-elf - SRCDIR/configure --target mips-elf --prefix=INSTALLDIR \ - --exec-prefix=INSTALLDIR/H-i386-linux - make - make install - cd .. - mkdir cygwin32-x-mips-elf - cd cygwin32-x-mips-elf - SRCDIR/configure --build=i386-linux-gnu --host=i386-cygwin32 \ - --target=mips-elf --prefix=WININSTALLDIR \ - --exec-prefix=WININSTALLDIR/H-i386-cygwin32 - make - make install - - You would then copy the contents of WININSTALLDIR over to the Windows -machine, and run the resulting programs. - - -File: configure.info, Node: Supporting Canadian Cross, Prev: CCross in Cygnus Tree, Up: Canadian Cross - -6.7 Supporting Canadian Cross -============================= - -If you want to make it possible to build a program you are developing -using a Canadian Cross, you must take some care when writing your -configure and make rules. Simple cases will normally work correctly. -However, it is not hard to write configure and make tests which will -fail in a Canadian Cross. - -* Menu: - -* CCross in Configure:: Supporting Canadian Cross in Configure Scripts. -* CCross in Make:: Supporting Canadian Cross in Makefiles. - - -File: configure.info, Node: CCross in Configure, Next: CCross in Make, Up: Supporting Canadian Cross - -6.7.1 Supporting Canadian Cross in Configure Scripts ----------------------------------------------------- - -In a 'configure.in' file, after calling 'AC_PROG_CC', you can find out -whether this is a Canadian Cross configure by examining the shell -variable 'cross_compiling'. In a Canadian Cross, which means that the -compiler is a cross compiler, 'cross_compiling' will be 'yes'. In a -normal configuration, 'cross_compiling' will be 'no'. - - You ordinarily do not need to know the type of the build system in a -configure script. However, if you do need that information, you can get -it by using the macro 'AC_CANONICAL_SYSTEM', the same macro that is used -to determine the target system. This macro will set the variables -'build', 'build_alias', 'build_cpu', 'build_vendor', and 'build_os', -which correspond to the similar 'target' and 'host' variables, except -that they describe the build system. - - When writing tests in 'configure.in', you must remember that you want -to test the host environment, not the build environment. - - Macros like 'AC_CHECK_FUNCS' which use the compiler will test the -host environment. That is because the tests will be done by running the -compiler, which is actually a build cross host compiler. If the -compiler can find the function, that means that the function is present -in the host environment. - - Tests like 'test -f /dev/ptyp0', on the other hand, will test the -build environment. Remember that the configure script is running on the -build system, not the host system. If your configure scripts examines -files, those files will be on the build system. Whatever you determine -based on those files may or may not be the case on the host system. - - Most autoconf macros will work correctly for a Canadian Cross. The -main exception is 'AC_TRY_RUN'. This macro tries to compile and run a -test program. This will fail in a Canadian Cross, because the program -will be compiled for the host system, which means that it will not run -on the build system. - - The 'AC_TRY_RUN' macro provides an optional argument to tell the -configure script what to do in a Canadian Cross. If that argument is -not present, you will get a warning when you run 'autoconf': - warning: AC_TRY_RUN called without default to allow cross compiling -This tells you that the resulting 'configure' script will not work with -a Canadian Cross. - - In some cases while it may better to perform a test at configure -time, it is also possible to perform the test at run time. In such a -case you can use the cross compiling argument to 'AC_TRY_RUN' to tell -your program that the test could not be performed at configure time. - - There are a few other autoconf macros which will not work correctly -with a Canadian Cross: a partial list is 'AC_FUNC_GETPGRP', -'AC_FUNC_SETPGRP', 'AC_FUNC_SETVBUF_REVERSED', and -'AC_SYS_RESTARTABLE_SYSCALLS'. The 'AC_CHECK_SIZEOF' macro is generally -not very useful with a Canadian Cross; it permits an optional argument -indicating the default size, but there is no way to know what the -correct default should be. - - -File: configure.info, Node: CCross in Make, Prev: CCross in Configure, Up: Supporting Canadian Cross - -6.7.2 Supporting Canadian Cross in Makefiles. ---------------------------------------------- - -The main Canadian Cross issue in a 'Makefile' arises when you want to -use a subsidiary program to generate code or data which you will then -include in your real program. - - If you compile this subsidiary program using '$(CC)' in the usual -way, you will not be able to run it. This is because '$(CC)' will build -a program for the host system, but the program is being built on the -build system. - - You must instead use a compiler for the build system, rather than the -host system. In the Cygnus tree, this make variable '$(CC_FOR_BUILD)' -will hold a compiler for the build system. - - Note that you should not include 'config.h' in a file you are -compiling with '$(CC_FOR_BUILD)'. The 'configure' script will build -'config.h' with information for the host system. However, you are -compiling the file using a compiler for the build system (a native -compiler). Subsidiary programs are normally simple filters which do no -user interaction, and it is normally possible to write them in a highly -portable fashion so that the absence of 'config.h' is not crucial. - - The gcc 'Makefile.in' shows a complex situation in which certain -files, such as 'rtl.c', must be compiled into both subsidiary programs -run on the build system and into the final program. This approach may -be of interest for advanced build system hackers. Note that the build -system compiler is rather confusingly called 'HOST_CC'. - - -File: configure.info, Node: Cygnus Configure, Next: Multilibs, Prev: Canadian Cross, Up: Top - -7 Cygnus Configure -****************** - -The Cygnus configure script predates autoconf. All of its interesting -features have been incorporated into autoconf. No new programs should -be written to use the Cygnus configure script. - - However, the Cygnus configure script is still used in a few places: -at the top of the Cygnus tree and in a few target libraries in the -Cygnus tree. Until those uses have been replaced with autoconf, some -brief notes are appropriate here. This is not complete documentation, -but it should be possible to use this as a guide while examining the -scripts themselves. - -* Menu: - -* Cygnus Configure Basics:: Cygnus Configure Basics. -* Cygnus Configure in C++ Libraries:: Cygnus Configure in C++ Libraries. - - -File: configure.info, Node: Cygnus Configure Basics, Next: Cygnus Configure in C++ Libraries, Up: Cygnus Configure - -7.1 Cygnus Configure Basics -=========================== - -Cygnus configure does not use any generated files; there is no program -corresponding to 'autoconf'. Instead, there is a single shell script -named 'configure' which may be found at the top of the Cygnus tree. -This shell script was written by hand; it was not generated by autoconf, -and it is incorrect, and indeed harmful, to run 'autoconf' in the top -level of a Cygnus tree. - - Cygnus configure works in a particular directory by examining the -file 'configure.in' in that directory. That file is broken into four -separate shell scripts. - - The first is the contents of 'configure.in' up to a line that starts -with '# per-host:'. This is the common part. - - The second is the rest of 'configure.in' up to a line that starts -with '# per-target:'. This is the per host part. - - The third is the rest of 'configure.in' up to a line that starts with -'# post-target:'. This is the per target part. - - The fourth is the remainder of 'configure.in'. This is the post -target part. - - If any of these comment lines are missing, the corresponding shell -script is empty. - - Cygnus configure will first execute the common part. This must set -the shell variable 'srctrigger' to the name of a source file, to confirm -that Cygnus configure is looking at the right directory. This may set -the shell variables 'package_makefile_frag' and -'package_makefile_rules_frag'. - - Cygnus configure will next set the 'build' and 'host' shell -variables, and execute the per host part. This may set the shell -variable 'host_makefile_frag'. - - Cygnus configure will next set the 'target' variable, and execute the -per target part. This may set the shell variable -'target_makefile_frag'. - - Any of these scripts may set the 'subdirs' shell variable. This -variable is a list of subdirectories where a 'Makefile.in' file may be -found. Cygnus configure will automatically look for a 'Makefile.in' -file in the current directory. The 'subdirs' shell variable is not -normally used, and I believe that the only directory which uses it at -present is 'newlib'. - - For each 'Makefile.in', Cygnus configure will automatically create a -'Makefile' by adding definitions for 'make' variables such as 'host' and -'target', and automatically editing the values of 'make' variables such -as 'prefix' if they are present. - - Also, if any of the 'makefile_frag' shell variables are set, Cygnus -configure will interpret them as file names relative to either the -working directory or the source directory, and will read the contents of -the file into the generated 'Makefile'. The file contents will be read -in after the first line in 'Makefile.in' which starts with '####'. - - These 'Makefile' fragments are used to customize behaviour for a -particular host or target. They serve to select particular files to -compile, and to define particular preprocessor macros by providing -values for 'make' variables which are then used during compilation. -Cygnus configure, unlike autoconf, normally does not do feature tests, -and normally requires support to be added manually for each new host. - - The 'Makefile' fragment support is similar to the autoconf -'AC_SUBST_FILE' macro. - - After creating each 'Makefile', the post target script will be run -(i.e., it may be run several times). This script may further customize -the 'Makefile'. When it is run, the shell variable 'Makefile' will hold -the name of the 'Makefile', including the appropriate directory -component. - - Like an autoconf generated 'configure' script, Cygnus configure will -create a file named 'config.status' which, when run, will automatically -recreate the configuration. The 'config.status' file will simply -execute the Cygnus configure script again with the appropriate -arguments. - - Any of the parts of 'configure.in' may set the shell variables -'files' and 'links'. Cygnus configure will set up symlinks from the -names in 'links' to the files named in 'files'. This is similar to the -autoconf 'AC_LINK_FILES' macro. - - Finally, any of the parts of 'configure.in' may set the shell -variable 'configdirs' to a set of subdirectories. If it is set, Cygnus -configure will recursively run the configure process in each -subdirectory. If the subdirectory uses Cygnus configure, it will -contain a 'configure.in' file but no 'configure' file, in which case -Cygnus configure will invoke itself recursively. If the subdirectory -has a 'configure' file, Cygnus configure assumes that it is an autoconf -generated 'configure' script, and simply invokes it directly. - - -File: configure.info, Node: Cygnus Configure in C++ Libraries, Prev: Cygnus Configure Basics, Up: Cygnus Configure - -7.2 Cygnus Configure in C++ Libraries -===================================== - -The C++ library configure system, written by Per Bothner, deserves -special mention. It uses Cygnus configure, but it does feature testing -like that done by autoconf generated 'configure' scripts. This approach -is used in the libraries 'libio', 'libstdc++', and 'libg++'. - - Most of the 'Makefile' information is written out by the shell script -'libio/config.shared'. Each 'configure.in' file sets certain shell -variables, and then invokes 'config.shared' to create two package -'Makefile' fragments. These fragments are then incorporated into the -resulting 'Makefile' by the Cygnus configure script. - - The file '_G_config.h' is created in the 'libio' object directory by -running the shell script 'libio/gen-params'. This shell script uses -feature tests to define macros and typedefs in '_G_config.h'. - - -File: configure.info, Node: Multilibs, Next: FAQ, Prev: Cygnus Configure, Up: Top - -8 Multilibs -*********** - -For some targets gcc may have different processor requirements depending -upon command line options. An obvious example is the '-msoft-float' -option supported on several processors. This option means that the -floating point registers are not available, which means that floating -point operations must be done by calling an emulation subroutine rather -than by using machine instructions. - - For such options, gcc is often configured to compile target libraries -twice: once with '-msoft-float' and once without. When gcc compiles -target libraries more than once, the resulting libraries are called -"multilibs". - - Multilibs are not really part of the GNU configure and build system, -but we discuss them here since they require support in the 'configure' -scripts and 'Makefile's used for target libraries. - -* Menu: - -* Multilibs in gcc:: Multilibs in gcc. -* Multilibs in Target Libraries:: Multilibs in Target Libraries. - - -File: configure.info, Node: Multilibs in gcc, Next: Multilibs in Target Libraries, Up: Multilibs - -8.1 Multilibs in gcc -==================== - -In gcc, multilibs are defined by setting the variable 'MULTILIB_OPTIONS' -in the target 'Makefile' fragment. Several other 'MULTILIB' variables -may also be defined there. *Note The Target Makefile Fragment: -(gcc)Target Fragment. - - If you have built gcc, you can see what multilibs it uses by running -it with the '-print-multi-lib' option. The output '.;' means that no -multilibs are used. In general, the output is a sequence of lines, one -per multilib. The first part of each line, up to the ';', is the name -of the multilib directory. The second part is a list of compiler -options separated by '@' characters. - - Multilibs are built in a tree of directories. The top of the tree, -represented by '.' in the list of multilib directories, is the default -library to use when no special compiler options are used. The -subdirectories of the tree hold versions of the library to use when -particular compiler options are used. - - -File: configure.info, Node: Multilibs in Target Libraries, Prev: Multilibs in gcc, Up: Multilibs - -8.2 Multilibs in Target Libraries -================================= - -The target libraries in the Cygnus tree are automatically built with -multilibs. That means that each library is built multiple times. - - This default is set in the top level 'configure.in' file, by adding -'--enable-multilib' to the list of arguments passed to configure when it -is run for the target libraries (*note Host and Target Libraries::). - - Each target library uses the shell script 'config-ml.in', written by -Doug Evans, to prepare to build target libraries. This shell script is -invoked after the 'Makefile' has been created by the 'configure' script. -If multilibs are not enabled, it does nothing, otherwise it modifies the -'Makefile' to support multilibs. - - The 'config-ml.in' script makes one copy of the 'Makefile' for each -multilib in the appropriate subdirectory. When configuring in the -source directory (which is not recommended), it will build a symlink -tree of the sources in each subdirectory. - - The 'config-ml.in' script sets several variables in the various -'Makefile's. The 'Makefile.in' must have definitions for these -variables already; 'config-ml.in' simply changes the existing values. -The 'Makefile' should use default values for these variables which will -do the right thing in the subdirectories. - -'MULTISRCTOP' - 'config-ml.in' will set this to a sequence of '../' strings, where - the number of strings is the number of multilib levels in the - source tree. The default value should be the empty string. -'MULTIBUILDTOP' - 'config-ml.in' will set this to a sequence of '../' strings, where - the number of strings is number of multilib levels in the object - directory. The default value should be the empty string. This - will differ from 'MULTISRCTOP' when configuring in the source tree - (which is not recommended). -'MULTIDIRS' - In the top level 'Makefile' only, 'config-ml.in' will set this to - the list of multilib subdirectories. The default value should be - the empty string. -'MULTISUBDIR' - 'config-ml.in' will set this to the installed subdirectory name to - use for this subdirectory, with a leading '/'. The default value - shold be the empty string. -'MULTIDO' -'MULTICLEAN' - In the top level 'Makefile' only, 'config-ml.in' will set these - variables to commands to use when doing a recursive make. These - variables should both default to the string 'true', so that by - default nothing happens. - - All references to the parent of the source directory should use the -variable 'MULTISRCTOP'. Instead of writing '$(srcdir)/..', you must -write '$(srcdir)/$(MULTISRCTOP)..'. - - Similarly, references to the parent of the object directory should -use the variable 'MULTIBUILDTOP'. - - In the installation target, the libraries should be installed in the -subdirectory 'MULTISUBDIR'. Instead of installing '$(libdir)/libfoo.a', -install '$(libdir)$(MULTISUBDIR)/libfoo.a'. - - The 'config-ml.in' script also modifies the top level 'Makefile' to -add 'multi-do' and 'multi-clean' targets which are used when building -multilibs. - - The default target of the 'Makefile' should include the following -command: - @$(MULTIDO) $(FLAGS_TO_PASS) DO=all multi-do -This assumes that '$(FLAGS_TO_PASS)' is defined as a set of variables to -pass to a recursive invocation of 'make'. This will build all the -multilibs. Note that the default value of 'MULTIDO' is 'true', so by -default this command will do nothing. It will only do something in the -top level 'Makefile' if multilibs were enabled. - - The 'install' target of the 'Makefile' should include the following -command: - @$(MULTIDO) $(FLAGS_TO_PASS) DO=install multi-do - - In general, any operation, other than clean, which should be -performed on all the multilibs should use a '$(MULTIDO)' line, setting -the variable 'DO' to the target of each recursive call to 'make'. - - The 'clean' targets ('clean', 'mostlyclean', etc.) should use -'$(MULTICLEAN)'. For example, the 'clean' target should do this: - @$(MULTICLEAN) DO=clean multi-clean - - -File: configure.info, Node: FAQ, Next: Index, Prev: Multilibs, Up: Top - -9 Frequently Asked Questions -**************************** - -Which do I run first, 'autoconf' or 'automake'? - Except when you first add autoconf or automake support to a - package, you shouldn't run either by hand. Instead, configure with - the '--enable-maintainer-mode' option, and let 'make' take care of - it. - -'autoconf' says something about undefined macros. - This means that you have macros in your 'configure.in' which are - not defined by 'autoconf'. You may be using an old version of - 'autoconf'; try building and installing a newer one. Make sure the - newly installled 'autoconf' is first on your 'PATH'. Also, see the - next question. - -My 'configure' script has stuff like 'CY_GNU_GETTEXT' in it. - This means that you have macros in your 'configure.in' which should - be defined in your 'aclocal.m4' file, but aren't. This usually - means that 'aclocal' was not able to appropriate definitions of the - macros. Make sure that you have installed all the packages you - need. In particular, make sure that you have installed libtool - (this is where 'AM_PROG_LIBTOOL' is defined) and gettext (this is - where 'CY_GNU_GETTEXT' is defined, at least in the Cygnus version - of gettext). - -My 'Makefile' has '@' characters in it. - This may mean that you tried to use an autoconf substitution in - your 'Makefile.in' without adding the appropriate 'AC_SUBST' call - to your 'configure' script. Or it may just mean that you need to - rebuild 'Makefile' in your build directory. To rebuild 'Makefile' - from 'Makefile.in', run the shell script 'config.status' with no - arguments. If you need to force 'configure' to run again, first - run 'config.status --recheck'. These runs are normally done - automatically by 'Makefile' targets, but if your 'Makefile' has - gotten messed up you'll need to help them along. - -Why do I have to run both 'config.status --recheck' and 'config.status'? - Normally, you don't; they will be run automatically by 'Makefile' - targets. If you do need to run them, use 'config.status --recheck' - to run the 'configure' script again with the same arguments as the - first time you ran it. Use 'config.status' (with no arguments) to - regenerate all files ('Makefile', 'config.h', etc.) based on the - results of the configure script. The two cases are separate - because it isn't always necessary to regenerate all the files after - running 'config.status --recheck'. The 'Makefile' targets - generated by automake will use the environment variables - 'CONFIG_FILES' and 'CONFIG_HEADERS' to only regenerate files as - they are needed. - -What is the Cygnus tree? - The Cygnus tree is used for various packages including gdb, the GNU - binutils, and egcs. It is also, of course, used for Cygnus - releases. It is the build system which was developed at Cygnus, - using the Cygnus configure script. It permits building many - different packages with a single configure and make. The configure - scripts in the tree are being converted to autoconf, but the - general build structure remains intact. - -Why do I have to keep rebuilding and reinstalling the tools? - I know, it's a pain. Unfortunately, there are bugs in the tools - themselves which need to be fixed, and each time that happens - everybody who uses the tools need to reinstall new versions of - them. I don't know if there is going to be a clever fix until the - tools stabilize. - -Why not just have a Cygnus tree 'make' target to update the tools? - The tools unfortunately need to be installed before they can be - used. That means that they must be built using an appropriate - prefix, and it seems unwise to assume that every configuration uses - an appropriate prefix. It might be possible to make them work in - place, or it might be possible to install them in some - subdirectory; so far these approaches have not been implemented. - - -File: configure.info, Node: Index, Prev: FAQ, Up: Top - -Index -***** - -[index] -* Menu: - -* '--build' option: Build and Host Options. - (line 9) -* '--host' option: Build and Host Options. - (line 14) -* '--target' option: Specifying the Target. - (line 10) -* '_GNU_SOURCE': Write configure.in. (line 132) -* 'acconfig.h': Written Developer Files. - (line 27) -* 'acconfig.h', writing: Write acconfig.h. (line 6) -* 'acinclude.m4': Written Developer Files. - (line 37) -* 'aclocal.m4': Generated Developer Files. - (line 33) -* 'AC_CANONICAL_HOST': Using the Host Type. (line 10) -* 'AC_CANONICAL_SYSTEM': Using the Target Type. - (line 6) -* 'AC_CONFIG_HEADER': Write configure.in. (line 64) -* 'AC_EXEEXT': Write configure.in. (line 84) -* 'AC_INIT': Write configure.in. (line 37) -* 'AC_OUTPUT': Write configure.in. (line 140) -* 'AC_PREREQ': Write configure.in. (line 41) -* 'AC_PROG_CC': Write configure.in. (line 101) -* 'AC_PROG_CXX': Write configure.in. (line 115) -* 'AM_CONFIG_HEADER': Write configure.in. (line 52) -* 'AM_DISABLE_SHARED': Write configure.in. (line 125) -* 'AM_EXEEXT': Write configure.in. (line 84) -* 'AM_INIT_AUTOMAKE': Write configure.in. (line 47) -* 'AM_MAINTAINER_MODE': Write configure.in. (line 68) -* 'AM_PROG_LIBTOOL': Write configure.in. (line 120) -* 'AM_PROG_LIBTOOL' in 'configure': FAQ. (line 19) -* build option: Build and Host Options. - (line 9) -* building with a cross compiler: Canadian Cross. (line 6) -* canadian cross: Canadian Cross. (line 6) -* canadian cross in configure: CCross in Configure. (line 6) -* canadian cross in cygnus tree: CCross in Cygnus Tree. - (line 6) -* canadian cross in makefile: CCross in Make. (line 6) -* canadian cross, configuring: Build and Host Options. - (line 6) -* canonical system names: Configuration Names. (line 6) -* 'config.cache': Build Files Description. - (line 28) -* 'config.h': Build Files Description. - (line 23) -* 'config.h.in': Generated Developer Files. - (line 45) -* 'config.in': Generated Developer Files. - (line 45) -* 'config.status': Build Files Description. - (line 9) -* 'config.status --recheck': FAQ. (line 40) -* configuration names: Configuration Names. (line 6) -* configuration triplets: Configuration Names. (line 6) -* 'configure': Generated Developer Files. - (line 21) -* configure build system: Build and Host Options. - (line 9) -* configure host: Build and Host Options. - (line 14) -* configure target: Specifying the Target. - (line 10) -* 'configure.in': Written Developer Files. - (line 9) -* 'configure.in', writing: Write configure.in. (line 6) -* configuring a canadian cross: Build and Host Options. - (line 6) -* cross compiler: Cross Compilation Concepts. - (line 6) -* cross compiler, building with: Canadian Cross. (line 6) -* cross tools: Cross Compilation Tools. - (line 6) -* cygnus configure: Cygnus Configure. (line 6) -* 'CY_GNU_GETTEXT' in 'configure': FAQ. (line 19) -* goals: Goals. (line 6) -* history: History. (line 6) -* host names: Configuration Names. (line 6) -* host option: Build and Host Options. - (line 14) -* host system: Host and Target. (line 6) -* host triplets: Configuration Names. (line 6) -* 'HOST_CC': CCross in Make. (line 27) -* 'libg++' configure: Cygnus Configure in C++ Libraries. - (line 6) -* 'libio' configure: Cygnus Configure in C++ Libraries. - (line 6) -* 'libstdc++' configure: Cygnus Configure in C++ Libraries. - (line 6) -* 'Makefile': Build Files Description. - (line 18) -* 'Makefile', garbage characters: FAQ. (line 29) -* 'Makefile.am': Written Developer Files. - (line 18) -* 'Makefile.am', writing: Write Makefile.am. (line 6) -* 'Makefile.in': Generated Developer Files. - (line 26) -* multilibs: Multilibs. (line 6) -* 'stamp-h': Build Files Description. - (line 40) -* 'stamp-h.in': Generated Developer Files. - (line 54) -* system names: Configuration Names. (line 6) -* system types: Configuration Names. (line 6) -* target option: Specifying the Target. - (line 10) -* target system: Host and Target. (line 6) -* triplets: Configuration Names. (line 6) -* undefined macros: FAQ. (line 12) - - - -Tag Table: -Node: Top966 -Node: Introduction1494 -Node: Goals2576 -Node: Tools3300 -Node: History4289 -Node: Building7285 -Node: Getting Started10548 -Node: Write configure.in11061 -Node: Write Makefile.am18275 -Node: Write acconfig.h21431 -Node: Generate files22968 -Node: Getting Started Example24934 -Node: Getting Started Example 125689 -Node: Getting Started Example 227610 -Node: Getting Started Example 330605 -Node: Generate Files in Example32966 -Node: Files34052 -Node: Developer Files34663 -Node: Developer Files Picture35043 -Node: Written Developer Files36343 -Node: Generated Developer Files38895 -Node: Build Files42039 -Node: Build Files Picture42700 -Node: Build Files Description43463 -Node: Support Files45463 -Node: Configuration Names48332 -Node: Configuration Name Definition48831 -Node: Using Configuration Names51151 -Node: Cross Compilation Tools53121 -Node: Cross Compilation Concepts53812 -Node: Host and Target54780 -Node: Using the Host Type56281 -Node: Specifying the Target57628 -Node: Using the Target Type58417 -Node: Cross Tools in the Cygnus Tree61847 -Node: Host and Target Libraries62904 -Node: Target Library Configure Scripts66649 -Node: Make Targets in Cygnus Tree69741 -Node: Target libiberty71089 -Node: Canadian Cross72475 -Node: Canadian Cross Example73316 -Node: Canadian Cross Concepts74435 -Node: Build Cross Host Tools75947 -Node: Build and Host Options76899 -Node: CCross not in Cygnus Tree78685 -Node: CCross in Cygnus Tree79663 -Node: Standard Cygnus CCross80084 -Node: Cross Cygnus CCross81448 -Node: Supporting Canadian Cross84248 -Node: CCross in Configure84863 -Node: CCross in Make88028 -Node: Cygnus Configure89631 -Node: Cygnus Configure Basics90466 -Node: Cygnus Configure in C++ Libraries95144 -Node: Multilibs96151 -Node: Multilibs in gcc97196 -Node: Multilibs in Target Libraries98274 -Node: FAQ102458 -Node: Index106559 - -End Tag Table diff --git a/libc/share/info/standards.info b/libc/share/info/standards.info deleted file mode 100644 index ba33f70..0000000 --- a/libc/share/info/standards.info +++ /dev/null @@ -1,5720 +0,0 @@ -This is standards.info, produced by makeinfo version 6.0 from -standards.texi. - -The GNU coding standards, last updated April 12, 2010. - - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -Foundation, Inc. - - Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the section entitled "GNU -Free Documentation License". -INFO-DIR-SECTION GNU organization -START-INFO-DIR-ENTRY -* Standards: (standards). GNU coding standards. -END-INFO-DIR-ENTRY - - -File: standards.info, Node: Top, Next: Preface, Prev: (dir), Up: (dir) - -Version -******* - -The GNU coding standards, last updated April 12, 2010. - - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software -Foundation, Inc. - - Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the section entitled "GNU -Free Documentation License". - -* Menu: - -* Preface:: About the GNU Coding Standards. -* Legal Issues:: Keeping free software free. -* Design Advice:: General program design. -* Program Behavior:: Program behavior for all programs -* Writing C:: Making the best use of C. -* Documentation:: Documenting programs. -* Managing Releases:: The release process. -* References:: Mentioning non-free software or documentation. -* GNU Free Documentation License:: Copying and sharing this manual. -* Index:: - - -File: standards.info, Node: Preface, Next: Legal Issues, Up: Top - -1 About the GNU Coding Standards -******************************** - -The GNU Coding Standards were written by Richard Stallman and other GNU -Project volunteers. Their purpose is to make the GNU system clean, -consistent, and easy to install. This document can also be read as a -guide to writing portable, robust and reliable programs. It focuses on -programs written in C, but many of the rules and principles are useful -even if you write in another programming language. The rules often -state reasons for writing in a certain way. - - If you did not obtain this file directly from the GNU project and -recently, please check for a newer version. You can get the GNU Coding -Standards from the GNU web server in many different formats, including -the Texinfo source, PDF, HTML, DVI, plain text, and more, at: -. - - If you are maintaining an official GNU package, in addition to this -document, please read and follow the GNU maintainer information (*note -Contents: (maintain)Top.). - - If you want to receive diffs for every change to these GNU documents, -join the mailing list 'gnustandards-commit@gnu.org', via the web -interface at -. Archives -are also available there. - - Please send corrections or suggestions for this document to -. If you make a suggestion, please include a -suggested new wording for it, to help us consider the suggestion -efficiently. We prefer a context diff to the Texinfo source, but if -that's difficult for you, you can make a context diff for some other -version of this document, or propose it in any way that makes it clear. -The source repository for this document can be found at -. - - These standards cover the minimum of what is important when writing a -GNU package. Likely, the need for additional standards will come up. -Sometimes, you might suggest that such standards be added to this -document. If you think your standards would be generally useful, please -do suggest them. - - You should also set standards for your package on many questions not -addressed or not firmly specified here. The most important point is to -be self-consistent--try to stick to the conventions you pick, and try to -document them as much as possible. That way, your program will be more -maintainable by others. - - The GNU Hello program serves as an example of how to follow the GNU -coding standards for a trivial program. -. - - This release of the GNU Coding Standards was last updated April 12, -2010. - - -File: standards.info, Node: Legal Issues, Next: Design Advice, Prev: Preface, Up: Top - -2 Keeping Free Software Free -**************************** - -This chapter discusses how you can make sure that GNU software avoids -legal difficulties, and other related issues. - -* Menu: - -* Reading Non-Free Code:: Referring to proprietary programs. -* Contributions:: Accepting contributions. -* Trademarks:: How we deal with trademark issues. - - -File: standards.info, Node: Reading Non-Free Code, Next: Contributions, Up: Legal Issues - -2.1 Referring to Proprietary Programs -===================================== - -Don't in any circumstances refer to Unix source code for or during your -work on GNU! (Or to any other proprietary programs.) - - If you have a vague recollection of the internals of a Unix program, -this does not absolutely mean you can't write an imitation of it, but do -try to organize the imitation internally along different lines, because -this is likely to make the details of the Unix version irrelevant and -dissimilar to your results. - - For example, Unix utilities were generally optimized to minimize -memory use; if you go for speed instead, your program will be very -different. You could keep the entire input file in memory and scan it -there instead of using stdio. Use a smarter algorithm discovered more -recently than the Unix program. Eliminate use of temporary files. Do -it in one pass instead of two (we did this in the assembler). - - Or, on the contrary, emphasize simplicity instead of speed. For some -applications, the speed of today's computers makes simpler algorithms -adequate. - - Or go for generality. For example, Unix programs often have static -tables or fixed-size strings, which make for arbitrary limits; use -dynamic allocation instead. Make sure your program handles NULs and -other funny characters in the input files. Add a programming language -for extensibility and write part of the program in that language. - - Or turn some parts of the program into independently usable -libraries. Or use a simple garbage collector instead of tracking -precisely when to free memory, or use a new GNU facility such as -obstacks. - - -File: standards.info, Node: Contributions, Next: Trademarks, Prev: Reading Non-Free Code, Up: Legal Issues - -2.2 Accepting Contributions -=========================== - -If the program you are working on is copyrighted by the Free Software -Foundation, then when someone else sends you a piece of code to add to -the program, we need legal papers to use it--just as we asked you to -sign papers initially. _Each_ person who makes a nontrivial -contribution to a program must sign some sort of legal papers in order -for us to have clear title to the program; the main author alone is not -enough. - - So, before adding in any contributions from other people, please tell -us, so we can arrange to get the papers. Then wait until we tell you -that we have received the signed papers, before you actually use the -contribution. - - This applies both before you release the program and afterward. If -you receive diffs to fix a bug, and they make significant changes, we -need legal papers for that change. - - This also applies to comments and documentation files. For copyright -law, comments and code are just text. Copyright applies to all kinds of -text, so we need legal papers for all kinds. - - We know it is frustrating to ask for legal papers; it's frustrating -for us as well. But if you don't wait, you are going out on a limb--for -example, what if the contributor's employer won't sign a disclaimer? -You might have to take that code out again! - - You don't need papers for changes of a few lines here or there, since -they are not significant for copyright purposes. Also, you don't need -papers if all you get from the suggestion is some ideas, not actual code -which you use. For example, if someone sent you one implementation, but -you write a different implementation of the same idea, you don't need to -get papers. - - The very worst thing is if you forget to tell us about the other -contributor. We could be very embarrassed in court some day as a -result. - - We have more detailed advice for maintainers of programs; if you have -reached the stage of actually maintaining a program for GNU (whether -released or not), please ask us for a copy. It is also available online -for your perusal: . - - -File: standards.info, Node: Trademarks, Prev: Contributions, Up: Legal Issues - -2.3 Trademarks -============== - -Please do not include any trademark acknowledgements in GNU software -packages or documentation. - - Trademark acknowledgements are the statements that such-and-such is a -trademark of so-and-so. The GNU Project has no objection to the basic -idea of trademarks, but these acknowledgements feel like kowtowing, and -there is no legal requirement for them, so we don't use them. - - What is legally required, as regards other people's trademarks, is to -avoid using them in ways which a reader might reasonably understand as -naming or labeling our own programs or activities. For example, since -"Objective C" is (or at least was) a trademark, we made sure to say that -we provide a "compiler for the Objective C language" rather than an -"Objective C compiler". The latter would have been meant as a shorter -way of saying the former, but it does not explicitly state the -relationship, so it could be misinterpreted as using "Objective C" as a -label for the compiler rather than for the language. - - Please don't use "win" as an abbreviation for Microsoft Windows in -GNU software or documentation. In hacker terminology, calling something -a "win" is a form of praise. If you wish to praise Microsoft Windows -when speaking on your own, by all means do so, but not in GNU software. -Usually we write the name "Windows" in full, but when brevity is very -important (as in file names and sometimes symbol names), we abbreviate -it to "w". For instance, the files and functions in Emacs that deal -with Windows start with 'w32'. - - -File: standards.info, Node: Design Advice, Next: Program Behavior, Prev: Legal Issues, Up: Top - -3 General Program Design -************************ - -This chapter discusses some of the issues you should take into account -when designing your program. - -* Menu: - -* Source Language:: Which languages to use. -* Compatibility:: Compatibility with other implementations. -* Using Extensions:: Using non-standard features. -* Standard C:: Using standard C features. -* Conditional Compilation:: Compiling code only if a conditional is true. - - -File: standards.info, Node: Source Language, Next: Compatibility, Up: Design Advice - -3.1 Which Languages to Use -========================== - -When you want to use a language that gets compiled and runs at high -speed, the best language to use is C. Using another language is like -using a non-standard feature: it will cause trouble for users. Even if -GCC supports the other language, users may find it inconvenient to have -to install the compiler for that other language in order to build your -program. For example, if you write your program in C++, people will -have to install the GNU C++ compiler in order to compile your program. - - C has one other advantage over C++ and other compiled languages: more -people know C, so more people will find it easy to read and modify the -program if it is written in C. - - So in general it is much better to use C, rather than the comparable -alternatives. - - But there are two exceptions to that conclusion: - - * It is no problem to use another language to write a tool - specifically intended for use with that language. That is because - the only people who want to build the tool will be those who have - installed the other language anyway. - - * If an application is of interest only to a narrow part of the - community, then the question of which language it is written in has - less effect on other people, so you may as well please yourself. - - Many programs are designed to be extensible: they include an -interpreter for a language that is higher level than C. Often much of -the program is written in that language, too. The Emacs editor -pioneered this technique. - - The standard extensibility interpreter for GNU software is Guile -(), which implements the language -Scheme (an especially clean and simple dialect of Lisp). Guile also -includes bindings for GTK+/GNOME, making it practical to write modern -GUI functionality within Guile. We don't reject programs written in -other "scripting languages" such as Perl and Python, but using Guile is -very important for the overall consistency of the GNU system. - - -File: standards.info, Node: Compatibility, Next: Using Extensions, Prev: Source Language, Up: Design Advice - -3.2 Compatibility with Other Implementations -============================================ - -With occasional exceptions, utility programs and libraries for GNU -should be upward compatible with those in Berkeley Unix, and upward -compatible with Standard C if Standard C specifies their behavior, and -upward compatible with POSIX if POSIX specifies their behavior. - - When these standards conflict, it is useful to offer compatibility -modes for each of them. - - Standard C and POSIX prohibit many kinds of extensions. Feel free to -make the extensions anyway, and include a '--ansi', '--posix', or -'--compatible' option to turn them off. However, if the extension has a -significant chance of breaking any real programs or scripts, then it is -not really upward compatible. So you should try to redesign its -interface to make it upward compatible. - - Many GNU programs suppress extensions that conflict with POSIX if the -environment variable 'POSIXLY_CORRECT' is defined (even if it is defined -with a null value). Please make your program recognize this variable if -appropriate. - - When a feature is used only by users (not by programs or command -files), and it is done poorly in Unix, feel free to replace it -completely with something totally different and better. (For example, -'vi' is replaced with Emacs.) But it is nice to offer a compatible -feature as well. (There is a free 'vi' clone, so we offer it.) - - Additional useful features are welcome regardless of whether there is -any precedent for them. - - -File: standards.info, Node: Using Extensions, Next: Standard C, Prev: Compatibility, Up: Design Advice - -3.3 Using Non-standard Features -=============================== - -Many GNU facilities that already exist support a number of convenient -extensions over the comparable Unix facilities. Whether to use these -extensions in implementing your program is a difficult question. - - On the one hand, using the extensions can make a cleaner program. On -the other hand, people will not be able to build the program unless the -other GNU tools are available. This might cause the program to work on -fewer kinds of machines. - - With some extensions, it might be easy to provide both alternatives. -For example, you can define functions with a "keyword" 'INLINE' and -define that as a macro to expand into either 'inline' or nothing, -depending on the compiler. - - In general, perhaps it is best not to use the extensions if you can -straightforwardly do without them, but to use the extensions if they are -a big improvement. - - An exception to this rule are the large, established programs (such -as Emacs) which run on a great variety of systems. Using GNU extensions -in such programs would make many users unhappy, so we don't do that. - - Another exception is for programs that are used as part of -compilation: anything that must be compiled with other compilers in -order to bootstrap the GNU compilation facilities. If these require the -GNU compiler, then no one can compile them without having them installed -already. That would be extremely troublesome in certain cases. - - -File: standards.info, Node: Standard C, Next: Conditional Compilation, Prev: Using Extensions, Up: Design Advice - -3.4 Standard C and Pre-Standard C -================================= - -1989 Standard C is widespread enough now that it is ok to use its -features in new programs. There is one exception: do not ever use the -"trigraph" feature of Standard C. - - 1999 Standard C is not widespread yet, so please do not require its -features in programs. It is ok to use its features if they are present. - - However, it is easy to support pre-standard compilers in most -programs, so if you know how to do that, feel free. If a program you -are maintaining has such support, you should try to keep it working. - - To support pre-standard C, instead of writing function definitions in -standard prototype form, - - int - foo (int x, int y) - ... - -write the definition in pre-standard style like this, - - int - foo (x, y) - int x, y; - ... - -and use a separate declaration to specify the argument prototype: - - int foo (int, int); - - You need such a declaration anyway, in a header file, to get the -benefit of prototypes in all the files where the function is called. -And once you have the declaration, you normally lose nothing by writing -the function definition in the pre-standard style. - - This technique does not work for integer types narrower than 'int'. -If you think of an argument as being of a type narrower than 'int', -declare it as 'int' instead. - - There are a few special cases where this technique is hard to use. -For example, if a function argument needs to hold the system type -'dev_t', you run into trouble, because 'dev_t' is shorter than 'int' on -some machines; but you cannot use 'int' instead, because 'dev_t' is -wider than 'int' on some machines. There is no type you can safely use -on all machines in a non-standard definition. The only way to support -non-standard C and pass such an argument is to check the width of -'dev_t' using Autoconf and choose the argument type accordingly. This -may not be worth the trouble. - - In order to support pre-standard compilers that do not recognize -prototypes, you may want to use a preprocessor macro like this: - - /* Declare the prototype for a general external function. */ - #if defined (__STDC__) || defined (WINDOWSNT) - #define P_(proto) proto - #else - #define P_(proto) () - #endif - - -File: standards.info, Node: Conditional Compilation, Prev: Standard C, Up: Design Advice - -3.5 Conditional Compilation -=========================== - -When supporting configuration options already known when building your -program we prefer using 'if (... )' over conditional compilation, as in -the former case the compiler is able to perform more extensive checking -of all possible code paths. - - For example, please write - - if (HAS_FOO) - ... - else - ... - -instead of: - - #ifdef HAS_FOO - ... - #else - ... - #endif - - A modern compiler such as GCC will generate exactly the same code in -both cases, and we have been using similar techniques with good success -in several projects. Of course, the former method assumes that -'HAS_FOO' is defined as either 0 or 1. - - While this is not a silver bullet solving all portability problems, -and is not always appropriate, following this policy would have saved -GCC developers many hours, or even days, per year. - - In the case of function-like macros like 'REVERSIBLE_CC_MODE' in GCC -which cannot be simply used in 'if (...)' statements, there is an easy -workaround. Simply introduce another macro 'HAS_REVERSIBLE_CC_MODE' as -in the following example: - - #ifdef REVERSIBLE_CC_MODE - #define HAS_REVERSIBLE_CC_MODE 1 - #else - #define HAS_REVERSIBLE_CC_MODE 0 - #endif - - -File: standards.info, Node: Program Behavior, Next: Writing C, Prev: Design Advice, Up: Top - -4 Program Behavior for All Programs -*********************************** - -This chapter describes conventions for writing robust software. It also -describes general standards for error messages, the command line -interface, and how libraries should behave. - -* Menu: - -* Non-GNU Standards:: We consider standards such as POSIX; - we don't "obey" them. -* Semantics:: Writing robust programs. -* Libraries:: Library behavior. -* Errors:: Formatting error messages. -* User Interfaces:: Standards about interfaces generally. -* Graphical Interfaces:: Standards for graphical interfaces. -* Command-Line Interfaces:: Standards for command line interfaces. -* Option Table:: Table of long options. -* OID Allocations:: Table of OID slots for GNU. -* Memory Usage:: When and how to care about memory needs. -* File Usage:: Which files to use, and where. - - -File: standards.info, Node: Non-GNU Standards, Next: Semantics, Up: Program Behavior - -4.1 Non-GNU Standards -===================== - -The GNU Project regards standards published by other organizations as -suggestions, not orders. We consider those standards, but we do not -"obey" them. In developing a GNU program, you should implement an -outside standard's specifications when that makes the GNU system better -overall in an objective sense. When it doesn't, you shouldn't. - - In most cases, following published standards is convenient for -users--it means that their programs or scripts will work more portably. -For instance, GCC implements nearly all the features of Standard C as -specified by that standard. C program developers would be unhappy if it -did not. And GNU utilities mostly follow specifications of POSIX.2; -shell script writers and users would be unhappy if our programs were -incompatible. - - But we do not follow either of these specifications rigidly, and -there are specific points on which we decided not to follow them, so as -to make the GNU system better for users. - - For instance, Standard C says that nearly all extensions to C are -prohibited. How silly! GCC implements many extensions, some of which -were later adopted as part of the standard. If you want these -constructs to give an error message as "required" by the standard, you -must specify '--pedantic', which was implemented only so that we can say -"GCC is a 100% implementation of the standard," not because there is any -reason to actually use it. - - POSIX.2 specifies that 'df' and 'du' must output sizes by default in -units of 512 bytes. What users want is units of 1k, so that is what we -do by default. If you want the ridiculous behavior "required" by POSIX, -you must set the environment variable 'POSIXLY_CORRECT' (which was -originally going to be named 'POSIX_ME_HARDER'). - - GNU utilities also depart from the letter of the POSIX.2 -specification when they support long-named command-line options, and -intermixing options with ordinary arguments. This minor incompatibility -with POSIX is never a problem in practice, and it is very useful. - - In particular, don't reject a new feature, or remove an old one, -merely because a standard says it is "forbidden" or "deprecated." - - -File: standards.info, Node: Semantics, Next: Libraries, Prev: Non-GNU Standards, Up: Program Behavior - -4.2 Writing Robust Programs -=========================== - -Avoid arbitrary limits on the length or number of _any_ data structure, -including file names, lines, files, and symbols, by allocating all data -structures dynamically. In most Unix utilities, "long lines are -silently truncated". This is not acceptable in a GNU utility. - - Utilities reading files should not drop NUL characters, or any other -nonprinting characters _including those with codes above 0177_. The -only sensible exceptions would be utilities specifically intended for -interface to certain types of terminals or printers that can't handle -those characters. Whenever possible, try to make programs work properly -with sequences of bytes that represent multibyte characters, using -encodings such as UTF-8 and others. - - Check every system call for an error return, unless you know you wish -to ignore errors. Include the system error text (from 'perror' or -equivalent) in _every_ error message resulting from a failing system -call, as well as the name of the file if any and the name of the -utility. Just "cannot open foo.c" or "stat failed" is not sufficient. - - Check every call to 'malloc' or 'realloc' to see if it returned zero. -Check 'realloc' even if you are making the block smaller; in a system -that rounds block sizes to a power of 2, 'realloc' may get a different -block if you ask for less space. - - In Unix, 'realloc' can destroy the storage block if it returns zero. -GNU 'realloc' does not have this bug: if it fails, the original block is -unchanged. Feel free to assume the bug is fixed. If you wish to run -your program on Unix, and wish to avoid lossage in this case, you can -use the GNU 'malloc'. - - You must expect 'free' to alter the contents of the block that was -freed. Anything you want to fetch from the block, you must fetch before -calling 'free'. - - If 'malloc' fails in a noninteractive program, make that a fatal -error. In an interactive program (one that reads commands from the -user), it is better to abort the command and return to the command -reader loop. This allows the user to kill other processes to free up -virtual memory, and then try the command again. - - Use 'getopt_long' to decode arguments, unless the argument syntax -makes this unreasonable. - - When static storage is to be written in during program execution, use -explicit C code to initialize it. Reserve C initialized declarations -for data that will not be changed. - - Try to avoid low-level interfaces to obscure Unix data structures -(such as file directories, utmp, or the layout of kernel memory), since -these are less likely to work compatibly. If you need to find all the -files in a directory, use 'readdir' or some other high-level interface. -These are supported compatibly by GNU. - - The preferred signal handling facilities are the BSD variant of -'signal', and the POSIX 'sigaction' function; the alternative USG -'signal' interface is an inferior design. - - Nowadays, using the POSIX signal functions may be the easiest way to -make a program portable. If you use 'signal', then on GNU/Linux systems -running GNU libc version 1, you should include 'bsd/signal.h' instead of -'signal.h', so as to get BSD behavior. It is up to you whether to -support systems where 'signal' has only the USG behavior, or give up on -them. - - In error checks that detect "impossible" conditions, just abort. -There is usually no point in printing any message. These checks -indicate the existence of bugs. Whoever wants to fix the bugs will have -to read the source code and run a debugger. So explain the problem with -comments in the source. The relevant data will be in variables, which -are easy to examine with the debugger, so there is no point moving them -elsewhere. - - Do not use a count of errors as the exit status for a program. _That -does not work_, because exit status values are limited to 8 bits (0 -through 255). A single run of the program might have 256 errors; if you -try to return 256 as the exit status, the parent process will see 0 as -the status, and it will appear that the program succeeded. - - If you make temporary files, check the 'TMPDIR' environment variable; -if that variable is defined, use the specified directory instead of -'/tmp'. - - In addition, be aware that there is a possible security problem when -creating temporary files in world-writable directories. In C, you can -avoid this problem by creating temporary files in this manner: - - fd = open (filename, O_WRONLY | O_CREAT | O_EXCL, 0600); - -or by using the 'mkstemps' function from libiberty. - - In bash, use 'set -C' to avoid this problem. - - -File: standards.info, Node: Libraries, Next: Errors, Prev: Semantics, Up: Program Behavior - -4.3 Library Behavior -==================== - -Try to make library functions reentrant. If they need to do dynamic -storage allocation, at least try to avoid any nonreentrancy aside from -that of 'malloc' itself. - - Here are certain name conventions for libraries, to avoid name -conflicts. - - Choose a name prefix for the library, more than two characters long. -All external function and variable names should start with this prefix. -In addition, there should only be one of these in any given library -member. This usually means putting each one in a separate source file. - - An exception can be made when two external symbols are always used -together, so that no reasonable program could use one without the other; -then they can both go in the same file. - - External symbols that are not documented entry points for the user -should have names beginning with '_'. The '_' should be followed by the -chosen name prefix for the library, to prevent collisions with other -libraries. These can go in the same files with user entry points if you -like. - - Static functions and variables can be used as you like and need not -fit any naming convention. - - -File: standards.info, Node: Errors, Next: User Interfaces, Prev: Libraries, Up: Program Behavior - -4.4 Formatting Error Messages -============================= - -Error messages from compilers should look like this: - - SOURCE-FILE-NAME:LINENO: MESSAGE - -If you want to mention the column number, use one of these formats: - - SOURCE-FILE-NAME:LINENO:COLUMN: MESSAGE - SOURCE-FILE-NAME:LINENO.COLUMN: MESSAGE - - -Line numbers should start from 1 at the beginning of the file, and -column numbers should start from 1 at the beginning of the line. (Both -of these conventions are chosen for compatibility.) Calculate column -numbers assuming that space and all ASCII printing characters have equal -width, and assuming tab stops every 8 columns. - - The error message can also give both the starting and ending -positions of the erroneous text. There are several formats so that you -can avoid redundant information such as a duplicate line number. Here -are the possible formats: - - SOURCE-FILE-NAME:LINENO-1.COLUMN-1-LINENO-2.COLUMN-2: MESSAGE - SOURCE-FILE-NAME:LINENO-1.COLUMN-1-COLUMN-2: MESSAGE - SOURCE-FILE-NAME:LINENO-1-LINENO-2: MESSAGE - -When an error is spread over several files, you can use this format: - - FILE-1:LINENO-1.COLUMN-1-FILE-2:LINENO-2.COLUMN-2: MESSAGE - - Error messages from other noninteractive programs should look like -this: - - PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE - -when there is an appropriate source file, or like this: - - PROGRAM: MESSAGE - -when there is no relevant source file. - - If you want to mention the column number, use this format: - - PROGRAM:SOURCE-FILE-NAME:LINENO:COLUMN: MESSAGE - - In an interactive program (one that is reading commands from a -terminal), it is better not to include the program name in an error -message. The place to indicate which program is running is in the -prompt or with the screen layout. (When the same program runs with -input from a source other than a terminal, it is not interactive and -would do best to print error messages using the noninteractive style.) - - The string MESSAGE should not begin with a capital letter when it -follows a program name and/or file name, because that isn't the -beginning of a sentence. (The sentence conceptually starts at the -beginning of the line.) Also, it should not end with a period. - - Error messages from interactive programs, and other messages such as -usage messages, should start with a capital letter. But they should not -end with a period. - - -File: standards.info, Node: User Interfaces, Next: Graphical Interfaces, Prev: Errors, Up: Program Behavior - -4.5 Standards for Interfaces Generally -====================================== - -Please don't make the behavior of a utility depend on the name used to -invoke it. It is useful sometimes to make a link to a utility with a -different name, and that should not change what it does. - - Instead, use a run time option or a compilation switch or both to -select among the alternate behaviors. - - Likewise, please don't make the behavior of the program depend on the -type of output device it is used with. Device independence is an -important principle of the system's design; do not compromise it merely -to save someone from typing an option now and then. (Variation in error -message syntax when using a terminal is ok, because that is a side issue -that people do not depend on.) - - If you think one behavior is most useful when the output is to a -terminal, and another is most useful when the output is a file or a -pipe, then it is usually best to make the default behavior the one that -is useful with output to a terminal, and have an option for the other -behavior. - - Compatibility requires certain programs to depend on the type of -output device. It would be disastrous if 'ls' or 'sh' did not do so in -the way all users expect. In some of these cases, we supplement the -program with a preferred alternate version that does not depend on the -output device type. For example, we provide a 'dir' program much like -'ls' except that its default output format is always multi-column -format. - - -File: standards.info, Node: Graphical Interfaces, Next: Command-Line Interfaces, Prev: User Interfaces, Up: Program Behavior - -4.6 Standards for Graphical Interfaces -====================================== - -When you write a program that provides a graphical user interface, -please make it work with the X Window System and the GTK+ toolkit unless -the functionality specifically requires some alternative (for example, -"displaying jpeg images while in console mode"). - - In addition, please provide a command-line interface to control the -functionality. (In many cases, the graphical user interface can be a -separate program which invokes the command-line program.) This is so -that the same jobs can be done from scripts. - - Please also consider providing a D-bus interface for use from other -running programs, such as within GNOME. (GNOME used to use CORBA for -this, but that is being phased out.) In addition, consider providing a -library interface (for use from C), and perhaps a keyboard-driven -console interface (for use by users from console mode). Once you are -doing the work to provide the functionality and the graphical interface, -these won't be much extra work. - - -File: standards.info, Node: Command-Line Interfaces, Next: Option Table, Prev: Graphical Interfaces, Up: Program Behavior - -4.7 Standards for Command Line Interfaces -========================================= - -It is a good idea to follow the POSIX guidelines for the command-line -options of a program. The easiest way to do this is to use 'getopt' to -parse them. Note that the GNU version of 'getopt' will normally permit -options anywhere among the arguments unless the special argument '--' is -used. This is not what POSIX specifies; it is a GNU extension. - - Please define long-named options that are equivalent to the -single-letter Unix-style options. We hope to make GNU more user -friendly this way. This is easy to do with the GNU function -'getopt_long'. - - One of the advantages of long-named options is that they can be -consistent from program to program. For example, users should be able -to expect the "verbose" option of any GNU program which has one, to be -spelled precisely '--verbose'. To achieve this uniformity, look at the -table of common long-option names when you choose the option names for -your program (*note Option Table::). - - It is usually a good idea for file names given as ordinary arguments -to be input files only; any output files would be specified using -options (preferably '-o' or '--output'). Even if you allow an output -file name as an ordinary argument for compatibility, try to provide an -option as another way to specify it. This will lead to more consistency -among GNU utilities, and fewer idiosyncrasies for users to remember. - - All programs should support two standard options: '--version' and -'--help'. CGI programs should accept these as command-line options, and -also if given as the 'PATH_INFO'; for instance, visiting - in a browser should output the same -information as invoking 'p.cgi --help' from the command line. - -* Menu: - -* --version:: The standard output for -version. -* --help:: The standard output for -help. - - -File: standards.info, Node: --version, Next: --help, Up: Command-Line Interfaces - -4.7.1 '--version' ------------------ - -The standard '--version' option should direct the program to print -information about its name, version, origin and legal status, all on -standard output, and then exit successfully. Other options and -arguments should be ignored once this is seen, and the program should -not perform its normal function. - - The first line is meant to be easy for a program to parse; the -version number proper starts after the last space. In addition, it -contains the canonical name for this program, in this format: - - GNU Emacs 19.30 - -The program's name should be a constant string; _don't_ compute it from -'argv[0]'. The idea is to state the standard or canonical name for the -program, not its file name. There are other ways to find out the -precise file name where a command is found in 'PATH'. - - If the program is a subsidiary part of a larger package, mention the -package name in parentheses, like this: - - emacsserver (GNU Emacs) 19.30 - -If the package has a version number which is different from this -program's version number, you can mention the package version number -just before the close-parenthesis. - - If you _need_ to mention the version numbers of libraries which are -distributed separately from the package which contains this program, you -can do so by printing an additional line of version info for each -library you want to mention. Use the same format for these lines as for -the first line. - - Please do not mention all of the libraries that the program uses -"just for completeness"--that would produce a lot of unhelpful clutter. -Please mention library version numbers only if you find in practice that -they are very important to you in debugging. - - The following line, after the version number line or lines, should be -a copyright notice. If more than one copyright notice is called for, -put each on a separate line. - - Next should follow a line stating the license, preferably using one -of abbrevations below, and a brief statement that the program is free -software, and that users are free to copy and change it. Also mention -that there is no warranty, to the extent permitted by law. See -recommended wording below. - - It is ok to finish the output with a list of the major authors of the -program, as a way of giving credit. - - Here's an example of output that follows these rules: - - GNU hello 2.3 - Copyright (C) 2007 Free Software Foundation, Inc. - License GPLv3+: GNU GPL version 3 or later - This is free software: you are free to change and redistribute it. - There is NO WARRANTY, to the extent permitted by law. - - You should adapt this to your program, of course, filling in the -proper year, copyright holder, name of program, and the references to -distribution terms, and changing the rest of the wording as necessary. - - This copyright notice only needs to mention the most recent year in -which changes were made--there's no need to list the years for previous -versions' changes. You don't have to mention the name of the program in -these notices, if that is inconvenient, since it appeared in the first -line. (The rules are different for copyright notices in source files; -*note (maintain)Copyright Notices::.) - - Translations of the above lines must preserve the validity of the -copyright notices (*note Internationalization::). If the translation's -character set supports it, the '(C)' should be replaced with the -copyright symbol, as follows: - - (the official copyright symbol, which is the letter C in a circle); - - Write the word "Copyright" exactly like that, in English. Do not -translate it into another language. International treaties recognize -the English word "Copyright"; translations into other languages do not -have legal significance. - - Finally, here is the table of our suggested license abbreviations. -Any abbreviation can be followed by 'vVERSION[+]', meaning that -particular version, or later versions with the '+', as shown above. - - In the case of exceptions for extra permissions with the GPL, we use -'/' for a separator; the version number can follow the license -abbreviation as usual, as in the examples below. - -GPL - GNU General Public License, . - -LGPL - GNU Lesser General Public License, - . - -GPL/Ada - GNU GPL with the exception for Ada. - -Apache - The Apache Software Foundation license, - . - -Artistic - The Artistic license used for Perl, - . - -Expat - The Expat license, . - -MPL - The Mozilla Public License, . - -OBSD - The original (4-clause) BSD license, incompatible with the GNU GPL - . - -PHP - The license used for PHP, . - -public domain - The non-license that is being in the public domain, - . - -Python - The license for Python, . - -RBSD - The revised (3-clause) BSD, compatible with the GNU GPL, - . - -X11 - The simple non-copyleft license used for most versions of the X - Window System, . - -Zlib - The license for Zlib, . - - More information about these licenses and many more are on the GNU -licensing web pages, . - - -File: standards.info, Node: --help, Prev: --version, Up: Command-Line Interfaces - -4.7.2 '--help' --------------- - -The standard '--help' option should output brief documentation for how -to invoke the program, on standard output, then exit successfully. -Other options and arguments should be ignored once this is seen, and the -program should not perform its normal function. - - Near the end of the '--help' option's output, please place lines -giving the email address for bug reports, the package's home page -(normally 'http://www.gnu.org/software/PKG', and the general page for -help using GNU programs. The format should be like this: - - Report bugs to: MAILING-ADDRESS - PKG home page: - General help using GNU software: - - It is ok to mention other appropriate mailing lists and web pages. - - -File: standards.info, Node: Option Table, Next: OID Allocations, Prev: Command-Line Interfaces, Up: Program Behavior - -4.8 Table of Long Options -========================= - -Here is a table of long options used by GNU programs. It is surely -incomplete, but we aim to list all the options that a new program might -want to be compatible with. If you use names not already in the table, -please send a list of them, with their meanings, -so we can update the table. - -'after-date' - '-N' in 'tar'. - -'all' - '-a' in 'du', 'ls', 'nm', 'stty', 'uname', and 'unexpand'. - -'all-text' - '-a' in 'diff'. - -'almost-all' - '-A' in 'ls'. - -'append' - '-a' in 'etags', 'tee', 'time'; '-r' in 'tar'. - -'archive' - '-a' in 'cp'. - -'archive-name' - '-n' in 'shar'. - -'arglength' - '-l' in 'm4'. - -'ascii' - '-a' in 'diff'. - -'assign' - '-v' in 'gawk'. - -'assume-new' - '-W' in 'make'. - -'assume-old' - '-o' in 'make'. - -'auto-check' - '-a' in 'recode'. - -'auto-pager' - '-a' in 'wdiff'. - -'auto-reference' - '-A' in 'ptx'. - -'avoid-wraps' - '-n' in 'wdiff'. - -'background' - For server programs, run in the background. - -'backward-search' - '-B' in 'ctags'. - -'basename' - '-f' in 'shar'. - -'batch' - Used in GDB. - -'baud' - Used in GDB. - -'before' - '-b' in 'tac'. - -'binary' - '-b' in 'cpio' and 'diff'. - -'bits-per-code' - '-b' in 'shar'. - -'block-size' - Used in 'cpio' and 'tar'. - -'blocks' - '-b' in 'head' and 'tail'. - -'break-file' - '-b' in 'ptx'. - -'brief' - Used in various programs to make output shorter. - -'bytes' - '-c' in 'head', 'split', and 'tail'. - -'c++' - '-C' in 'etags'. - -'catenate' - '-A' in 'tar'. - -'cd' - Used in various programs to specify the directory to use. - -'changes' - '-c' in 'chgrp' and 'chown'. - -'classify' - '-F' in 'ls'. - -'colons' - '-c' in 'recode'. - -'command' - '-c' in 'su'; '-x' in GDB. - -'compare' - '-d' in 'tar'. - -'compat' - Used in 'gawk'. - -'compress' - '-Z' in 'tar' and 'shar'. - -'concatenate' - '-A' in 'tar'. - -'confirmation' - '-w' in 'tar'. - -'context' - Used in 'diff'. - -'copyleft' - '-W copyleft' in 'gawk'. - -'copyright' - '-C' in 'ptx', 'recode', and 'wdiff'; '-W copyright' in 'gawk'. - -'core' - Used in GDB. - -'count' - '-q' in 'who'. - -'count-links' - '-l' in 'du'. - -'create' - Used in 'tar' and 'cpio'. - -'cut-mark' - '-c' in 'shar'. - -'cxref' - '-x' in 'ctags'. - -'date' - '-d' in 'touch'. - -'debug' - '-d' in 'make' and 'm4'; '-t' in Bison. - -'define' - '-D' in 'm4'. - -'defines' - '-d' in Bison and 'ctags'. - -'delete' - '-D' in 'tar'. - -'dereference' - '-L' in 'chgrp', 'chown', 'cpio', 'du', 'ls', and 'tar'. - -'dereference-args' - '-D' in 'du'. - -'device' - Specify an I/O device (special file name). - -'diacritics' - '-d' in 'recode'. - -'dictionary-order' - '-d' in 'look'. - -'diff' - '-d' in 'tar'. - -'digits' - '-n' in 'csplit'. - -'directory' - Specify the directory to use, in various programs. In 'ls', it - means to show directories themselves rather than their contents. - In 'rm' and 'ln', it means to not treat links to directories - specially. - -'discard-all' - '-x' in 'strip'. - -'discard-locals' - '-X' in 'strip'. - -'dry-run' - '-n' in 'make'. - -'ed' - '-e' in 'diff'. - -'elide-empty-files' - '-z' in 'csplit'. - -'end-delete' - '-x' in 'wdiff'. - -'end-insert' - '-z' in 'wdiff'. - -'entire-new-file' - '-N' in 'diff'. - -'environment-overrides' - '-e' in 'make'. - -'eof' - '-e' in 'xargs'. - -'epoch' - Used in GDB. - -'error-limit' - Used in 'makeinfo'. - -'error-output' - '-o' in 'm4'. - -'escape' - '-b' in 'ls'. - -'exclude-from' - '-X' in 'tar'. - -'exec' - Used in GDB. - -'exit' - '-x' in 'xargs'. - -'exit-0' - '-e' in 'unshar'. - -'expand-tabs' - '-t' in 'diff'. - -'expression' - '-e' in 'sed'. - -'extern-only' - '-g' in 'nm'. - -'extract' - '-i' in 'cpio'; '-x' in 'tar'. - -'faces' - '-f' in 'finger'. - -'fast' - '-f' in 'su'. - -'fatal-warnings' - '-E' in 'm4'. - -'file' - '-f' in 'gawk', 'info', 'make', 'mt', 'sed', and 'tar'. - -'field-separator' - '-F' in 'gawk'. - -'file-prefix' - '-b' in Bison. - -'file-type' - '-F' in 'ls'. - -'files-from' - '-T' in 'tar'. - -'fill-column' - Used in 'makeinfo'. - -'flag-truncation' - '-F' in 'ptx'. - -'fixed-output-files' - '-y' in Bison. - -'follow' - '-f' in 'tail'. - -'footnote-style' - Used in 'makeinfo'. - -'force' - '-f' in 'cp', 'ln', 'mv', and 'rm'. - -'force-prefix' - '-F' in 'shar'. - -'foreground' - For server programs, run in the foreground; in other words, don't - do anything special to run the server in the background. - -'format' - Used in 'ls', 'time', and 'ptx'. - -'freeze-state' - '-F' in 'm4'. - -'fullname' - Used in GDB. - -'gap-size' - '-g' in 'ptx'. - -'get' - '-x' in 'tar'. - -'graphic' - '-i' in 'ul'. - -'graphics' - '-g' in 'recode'. - -'group' - '-g' in 'install'. - -'gzip' - '-z' in 'tar' and 'shar'. - -'hashsize' - '-H' in 'm4'. - -'header' - '-h' in 'objdump' and 'recode' - -'heading' - '-H' in 'who'. - -'help' - Used to ask for brief usage information. - -'here-delimiter' - '-d' in 'shar'. - -'hide-control-chars' - '-q' in 'ls'. - -'html' - In 'makeinfo', output HTML. - -'idle' - '-u' in 'who'. - -'ifdef' - '-D' in 'diff'. - -'ignore' - '-I' in 'ls'; '-x' in 'recode'. - -'ignore-all-space' - '-w' in 'diff'. - -'ignore-backups' - '-B' in 'ls'. - -'ignore-blank-lines' - '-B' in 'diff'. - -'ignore-case' - '-f' in 'look' and 'ptx'; '-i' in 'diff' and 'wdiff'. - -'ignore-errors' - '-i' in 'make'. - -'ignore-file' - '-i' in 'ptx'. - -'ignore-indentation' - '-I' in 'etags'. - -'ignore-init-file' - '-f' in Oleo. - -'ignore-interrupts' - '-i' in 'tee'. - -'ignore-matching-lines' - '-I' in 'diff'. - -'ignore-space-change' - '-b' in 'diff'. - -'ignore-zeros' - '-i' in 'tar'. - -'include' - '-i' in 'etags'; '-I' in 'm4'. - -'include-dir' - '-I' in 'make'. - -'incremental' - '-G' in 'tar'. - -'info' - '-i', '-l', and '-m' in Finger. - -'init-file' - In some programs, specify the name of the file to read as the - user's init file. - -'initial' - '-i' in 'expand'. - -'initial-tab' - '-T' in 'diff'. - -'inode' - '-i' in 'ls'. - -'interactive' - '-i' in 'cp', 'ln', 'mv', 'rm'; '-e' in 'm4'; '-p' in 'xargs'; '-w' - in 'tar'. - -'intermix-type' - '-p' in 'shar'. - -'iso-8601' - Used in 'date' - -'jobs' - '-j' in 'make'. - -'just-print' - '-n' in 'make'. - -'keep-going' - '-k' in 'make'. - -'keep-files' - '-k' in 'csplit'. - -'kilobytes' - '-k' in 'du' and 'ls'. - -'language' - '-l' in 'etags'. - -'less-mode' - '-l' in 'wdiff'. - -'level-for-gzip' - '-g' in 'shar'. - -'line-bytes' - '-C' in 'split'. - -'lines' - Used in 'split', 'head', and 'tail'. - -'link' - '-l' in 'cpio'. - -'lint' -'lint-old' - Used in 'gawk'. - -'list' - '-t' in 'cpio'; '-l' in 'recode'. - -'list' - '-t' in 'tar'. - -'literal' - '-N' in 'ls'. - -'load-average' - '-l' in 'make'. - -'login' - Used in 'su'. - -'machine' - Used in 'uname'. - -'macro-name' - '-M' in 'ptx'. - -'mail' - '-m' in 'hello' and 'uname'. - -'make-directories' - '-d' in 'cpio'. - -'makefile' - '-f' in 'make'. - -'mapped' - Used in GDB. - -'max-args' - '-n' in 'xargs'. - -'max-chars' - '-n' in 'xargs'. - -'max-lines' - '-l' in 'xargs'. - -'max-load' - '-l' in 'make'. - -'max-procs' - '-P' in 'xargs'. - -'mesg' - '-T' in 'who'. - -'message' - '-T' in 'who'. - -'minimal' - '-d' in 'diff'. - -'mixed-uuencode' - '-M' in 'shar'. - -'mode' - '-m' in 'install', 'mkdir', and 'mkfifo'. - -'modification-time' - '-m' in 'tar'. - -'multi-volume' - '-M' in 'tar'. - -'name-prefix' - '-a' in Bison. - -'nesting-limit' - '-L' in 'm4'. - -'net-headers' - '-a' in 'shar'. - -'new-file' - '-W' in 'make'. - -'no-builtin-rules' - '-r' in 'make'. - -'no-character-count' - '-w' in 'shar'. - -'no-check-existing' - '-x' in 'shar'. - -'no-common' - '-3' in 'wdiff'. - -'no-create' - '-c' in 'touch'. - -'no-defines' - '-D' in 'etags'. - -'no-deleted' - '-1' in 'wdiff'. - -'no-dereference' - '-d' in 'cp'. - -'no-inserted' - '-2' in 'wdiff'. - -'no-keep-going' - '-S' in 'make'. - -'no-lines' - '-l' in Bison. - -'no-piping' - '-P' in 'shar'. - -'no-prof' - '-e' in 'gprof'. - -'no-regex' - '-R' in 'etags'. - -'no-sort' - '-p' in 'nm'. - -'no-splash' - Don't print a startup splash screen. - -'no-split' - Used in 'makeinfo'. - -'no-static' - '-a' in 'gprof'. - -'no-time' - '-E' in 'gprof'. - -'no-timestamp' - '-m' in 'shar'. - -'no-validate' - Used in 'makeinfo'. - -'no-wait' - Used in 'emacsclient'. - -'no-warn' - Used in various programs to inhibit warnings. - -'node' - '-n' in 'info'. - -'nodename' - '-n' in 'uname'. - -'nonmatching' - '-f' in 'cpio'. - -'nstuff' - '-n' in 'objdump'. - -'null' - '-0' in 'xargs'. - -'number' - '-n' in 'cat'. - -'number-nonblank' - '-b' in 'cat'. - -'numeric-sort' - '-n' in 'nm'. - -'numeric-uid-gid' - '-n' in 'cpio' and 'ls'. - -'nx' - Used in GDB. - -'old-archive' - '-o' in 'tar'. - -'old-file' - '-o' in 'make'. - -'one-file-system' - '-l' in 'tar', 'cp', and 'du'. - -'only-file' - '-o' in 'ptx'. - -'only-prof' - '-f' in 'gprof'. - -'only-time' - '-F' in 'gprof'. - -'options' - '-o' in 'getopt', 'fdlist', 'fdmount', 'fdmountd', and 'fdumount'. - -'output' - In various programs, specify the output file name. - -'output-prefix' - '-o' in 'shar'. - -'override' - '-o' in 'rm'. - -'overwrite' - '-c' in 'unshar'. - -'owner' - '-o' in 'install'. - -'paginate' - '-l' in 'diff'. - -'paragraph-indent' - Used in 'makeinfo'. - -'parents' - '-p' in 'mkdir' and 'rmdir'. - -'pass-all' - '-p' in 'ul'. - -'pass-through' - '-p' in 'cpio'. - -'port' - '-P' in 'finger'. - -'portability' - '-c' in 'cpio' and 'tar'. - -'posix' - Used in 'gawk'. - -'prefix-builtins' - '-P' in 'm4'. - -'prefix' - '-f' in 'csplit'. - -'preserve' - Used in 'tar' and 'cp'. - -'preserve-environment' - '-p' in 'su'. - -'preserve-modification-time' - '-m' in 'cpio'. - -'preserve-order' - '-s' in 'tar'. - -'preserve-permissions' - '-p' in 'tar'. - -'print' - '-l' in 'diff'. - -'print-chars' - '-L' in 'cmp'. - -'print-data-base' - '-p' in 'make'. - -'print-directory' - '-w' in 'make'. - -'print-file-name' - '-o' in 'nm'. - -'print-symdefs' - '-s' in 'nm'. - -'printer' - '-p' in 'wdiff'. - -'prompt' - '-p' in 'ed'. - -'proxy' - Specify an HTTP proxy. - -'query-user' - '-X' in 'shar'. - -'question' - '-q' in 'make'. - -'quiet' - Used in many programs to inhibit the usual output. Every program - accepting '--quiet' should accept '--silent' as a synonym. - -'quiet-unshar' - '-Q' in 'shar' - -'quote-name' - '-Q' in 'ls'. - -'rcs' - '-n' in 'diff'. - -'re-interval' - Used in 'gawk'. - -'read-full-blocks' - '-B' in 'tar'. - -'readnow' - Used in GDB. - -'recon' - '-n' in 'make'. - -'record-number' - '-R' in 'tar'. - -'recursive' - Used in 'chgrp', 'chown', 'cp', 'ls', 'diff', and 'rm'. - -'reference' - '-r' in 'touch'. - -'references' - '-r' in 'ptx'. - -'regex' - '-r' in 'tac' and 'etags'. - -'release' - '-r' in 'uname'. - -'reload-state' - '-R' in 'm4'. - -'relocation' - '-r' in 'objdump'. - -'rename' - '-r' in 'cpio'. - -'replace' - '-i' in 'xargs'. - -'report-identical-files' - '-s' in 'diff'. - -'reset-access-time' - '-a' in 'cpio'. - -'reverse' - '-r' in 'ls' and 'nm'. - -'reversed-ed' - '-f' in 'diff'. - -'right-side-defs' - '-R' in 'ptx'. - -'same-order' - '-s' in 'tar'. - -'same-permissions' - '-p' in 'tar'. - -'save' - '-g' in 'stty'. - -'se' - Used in GDB. - -'sentence-regexp' - '-S' in 'ptx'. - -'separate-dirs' - '-S' in 'du'. - -'separator' - '-s' in 'tac'. - -'sequence' - Used by 'recode' to chose files or pipes for sequencing passes. - -'shell' - '-s' in 'su'. - -'show-all' - '-A' in 'cat'. - -'show-c-function' - '-p' in 'diff'. - -'show-ends' - '-E' in 'cat'. - -'show-function-line' - '-F' in 'diff'. - -'show-tabs' - '-T' in 'cat'. - -'silent' - Used in many programs to inhibit the usual output. Every program - accepting '--silent' should accept '--quiet' as a synonym. - -'size' - '-s' in 'ls'. - -'socket' - Specify a file descriptor for a network server to use for its - socket, instead of opening and binding a new socket. This provides - a way to run, in a non-privileged process, a server that normally - needs a reserved port number. - -'sort' - Used in 'ls'. - -'source' - '-W source' in 'gawk'. - -'sparse' - '-S' in 'tar'. - -'speed-large-files' - '-H' in 'diff'. - -'split-at' - '-E' in 'unshar'. - -'split-size-limit' - '-L' in 'shar'. - -'squeeze-blank' - '-s' in 'cat'. - -'start-delete' - '-w' in 'wdiff'. - -'start-insert' - '-y' in 'wdiff'. - -'starting-file' - Used in 'tar' and 'diff' to specify which file within a directory - to start processing with. - -'statistics' - '-s' in 'wdiff'. - -'stdin-file-list' - '-S' in 'shar'. - -'stop' - '-S' in 'make'. - -'strict' - '-s' in 'recode'. - -'strip' - '-s' in 'install'. - -'strip-all' - '-s' in 'strip'. - -'strip-debug' - '-S' in 'strip'. - -'submitter' - '-s' in 'shar'. - -'suffix' - '-S' in 'cp', 'ln', 'mv'. - -'suffix-format' - '-b' in 'csplit'. - -'sum' - '-s' in 'gprof'. - -'summarize' - '-s' in 'du'. - -'symbolic' - '-s' in 'ln'. - -'symbols' - Used in GDB and 'objdump'. - -'synclines' - '-s' in 'm4'. - -'sysname' - '-s' in 'uname'. - -'tabs' - '-t' in 'expand' and 'unexpand'. - -'tabsize' - '-T' in 'ls'. - -'terminal' - '-T' in 'tput' and 'ul'. '-t' in 'wdiff'. - -'text' - '-a' in 'diff'. - -'text-files' - '-T' in 'shar'. - -'time' - Used in 'ls' and 'touch'. - -'timeout' - Specify how long to wait before giving up on some operation. - -'to-stdout' - '-O' in 'tar'. - -'total' - '-c' in 'du'. - -'touch' - '-t' in 'make', 'ranlib', and 'recode'. - -'trace' - '-t' in 'm4'. - -'traditional' - '-t' in 'hello'; '-W traditional' in 'gawk'; '-G' in 'ed', 'm4', - and 'ptx'. - -'tty' - Used in GDB. - -'typedefs' - '-t' in 'ctags'. - -'typedefs-and-c++' - '-T' in 'ctags'. - -'typeset-mode' - '-t' in 'ptx'. - -'uncompress' - '-z' in 'tar'. - -'unconditional' - '-u' in 'cpio'. - -'undefine' - '-U' in 'm4'. - -'undefined-only' - '-u' in 'nm'. - -'update' - '-u' in 'cp', 'ctags', 'mv', 'tar'. - -'usage' - Used in 'gawk'; same as '--help'. - -'uuencode' - '-B' in 'shar'. - -'vanilla-operation' - '-V' in 'shar'. - -'verbose' - Print more information about progress. Many programs support this. - -'verify' - '-W' in 'tar'. - -'version' - Print the version number. - -'version-control' - '-V' in 'cp', 'ln', 'mv'. - -'vgrind' - '-v' in 'ctags'. - -'volume' - '-V' in 'tar'. - -'what-if' - '-W' in 'make'. - -'whole-size-limit' - '-l' in 'shar'. - -'width' - '-w' in 'ls' and 'ptx'. - -'word-regexp' - '-W' in 'ptx'. - -'writable' - '-T' in 'who'. - -'zeros' - '-z' in 'gprof'. - - -File: standards.info, Node: OID Allocations, Next: Memory Usage, Prev: Option Table, Up: Program Behavior - -4.9 OID Allocations -=================== - -The OID (object identifier) 1.3.6.1.4.1.11591 has been assigned to the -GNU Project (thanks to Werner Koch). These are used for SNMP, LDAP, -X.509 certificates, and so on. The web site - has a (voluntary) listing of many -OID assignments. - - If you need a new slot for your GNU package, write -. Here is a list of arcs currently assigned: - - - 1.3.6.1.4.1.11591 GNU - - 1.3.6.1.4.1.11591.1 GNU Radius - - 1.3.6.1.4.1.11591.2 GnuPG - 1.3.6.1.4.1.11591.2.1 notation - 1.3.6.1.4.1.11591.2.1.1 pkaAddress - - 1.3.6.1.4.1.11591.3 GNU Radar - - 1.3.6.1.4.1.11591.4 GNU GSS - - 1.3.6.1.4.1.11591.5 GNU Mailutils - - 1.3.6.1.4.1.11591.6 GNU Shishi - - 1.3.6.1.4.1.11591.7 GNU Radio - - 1.3.6.1.4.1.11591.12 digestAlgorithm - 1.3.6.1.4.1.11591.12.2 TIGER/192 - 1.3.6.1.4.1.11591.13 encryptionAlgorithm - 1.3.6.1.4.1.11591.13.2 Serpent - 1.3.6.1.4.1.11591.13.2.1 Serpent-128-ECB - 1.3.6.1.4.1.11591.13.2.2 Serpent-128-CBC - 1.3.6.1.4.1.11591.13.2.3 Serpent-128-OFB - 1.3.6.1.4.1.11591.13.2.4 Serpent-128-CFB - 1.3.6.1.4.1.11591.13.2.21 Serpent-192-ECB - 1.3.6.1.4.1.11591.13.2.22 Serpent-192-CBC - 1.3.6.1.4.1.11591.13.2.23 Serpent-192-OFB - 1.3.6.1.4.1.11591.13.2.24 Serpent-192-CFB - 1.3.6.1.4.1.11591.13.2.41 Serpent-256-ECB - 1.3.6.1.4.1.11591.13.2.42 Serpent-256-CBC - 1.3.6.1.4.1.11591.13.2.43 Serpent-256-OFB - 1.3.6.1.4.1.11591.13.2.44 Serpent-256-CFB - 1.3.6.1.4.1.11591.14 CRC algorithms - 1.3.6.1.4.1.11591.14.1 CRC 32 - - -File: standards.info, Node: Memory Usage, Next: File Usage, Prev: OID Allocations, Up: Program Behavior - -4.10 Memory Usage -================= - -If a program typically uses just a few meg of memory, don't bother -making any effort to reduce memory usage. For example, if it is -impractical for other reasons to operate on files more than a few meg -long, it is reasonable to read entire input files into memory to operate -on them. - - However, for programs such as 'cat' or 'tail', that can usefully -operate on very large files, it is important to avoid using a technique -that would artificially limit the size of files it can handle. If a -program works by lines and could be applied to arbitrary user-supplied -input files, it should keep only a line in memory, because this is not -very hard and users will want to be able to operate on input files that -are bigger than will fit in memory all at once. - - If your program creates complicated data structures, just make them -in memory and give a fatal error if 'malloc' returns zero. - - -File: standards.info, Node: File Usage, Prev: Memory Usage, Up: Program Behavior - -4.11 File Usage -=============== - -Programs should be prepared to operate when '/usr' and '/etc' are -read-only file systems. Thus, if the program manages log files, lock -files, backup files, score files, or any other files which are modified -for internal purposes, these files should not be stored in '/usr' or -'/etc'. - - There are two exceptions. '/etc' is used to store system -configuration information; it is reasonable for a program to modify -files in '/etc' when its job is to update the system configuration. -Also, if the user explicitly asks to modify one file in a directory, it -is reasonable for the program to store other files in the same -directory. - - -File: standards.info, Node: Writing C, Next: Documentation, Prev: Program Behavior, Up: Top - -5 Making The Best Use of C -************************** - -This chapter provides advice on how best to use the C language when -writing GNU software. - -* Menu: - -* Formatting:: Formatting your source code. -* Comments:: Commenting your work. -* Syntactic Conventions:: Clean use of C constructs. -* Names:: Naming variables, functions, and files. -* System Portability:: Portability among different operating systems. -* CPU Portability:: Supporting the range of CPU types. -* System Functions:: Portability and "standard" library functions. -* Internationalization:: Techniques for internationalization. -* Character Set:: Use ASCII by default. -* Quote Characters:: Use '...' in the C locale. -* Mmap:: How you can safely use 'mmap'. - - -File: standards.info, Node: Formatting, Next: Comments, Up: Writing C - -5.1 Formatting Your Source Code -=============================== - -It is important to put the open-brace that starts the body of a C -function in column one, so that they will start a defun. Several tools -look for open-braces in column one to find the beginnings of C -functions. These tools will not work on code not formatted that way. - - Avoid putting open-brace, open-parenthesis or open-bracket in column -one when they are inside a function, so that they won't start a defun. -The open-brace that starts a 'struct' body can go in column one if you -find it useful to treat that definition as a defun. - - It is also important for function definitions to start the name of -the function in column one. This helps people to search for function -definitions, and may also help certain tools recognize them. Thus, -using Standard C syntax, the format is this: - - static char * - concat (char *s1, char *s2) - { - ... - } - -or, if you want to use traditional C syntax, format the definition like -this: - - static char * - concat (s1, s2) /* Name starts in column one here */ - char *s1, *s2; - { /* Open brace in column one here */ - ... - } - - In Standard C, if the arguments don't fit nicely on one line, split -it like this: - - int - lots_of_args (int an_integer, long a_long, short a_short, - double a_double, float a_float) - ... - - The rest of this section gives our recommendations for other aspects -of C formatting style, which is also the default style of the 'indent' -program in version 1.2 and newer. It corresponds to the options - - -nbad -bap -nbc -bbo -bl -bli2 -bls -ncdb -nce -cp1 -cs -di2 - -ndj -nfc1 -nfca -hnl -i2 -ip5 -lp -pcs -psl -nsc -nsob - - We don't think of these recommendations as requirements, because it -causes no problems for users if two different programs have different -formatting styles. - - But whatever style you use, please use it consistently, since a -mixture of styles within one program tends to look ugly. If you are -contributing changes to an existing program, please follow the style of -that program. - - For the body of the function, our recommended style looks like this: - - if (x < foo (y, z)) - haha = bar[4] + 5; - else - { - while (z) - { - haha += foo (z, z); - z--; - } - return ++x + bar (); - } - - We find it easier to read a program when it has spaces before the -open-parentheses and after the commas. Especially after the commas. - - When you split an expression into multiple lines, split it before an -operator, not after one. Here is the right way: - - if (foo_this_is_long && bar > win (x, y, z) - && remaining_condition) - - Try to avoid having two operators of different precedence at the same -level of indentation. For example, don't write this: - - mode = (inmode[j] == VOIDmode - || GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j]) - ? outmode[j] : inmode[j]); - - Instead, use extra parentheses so that the indentation shows the -nesting: - - mode = ((inmode[j] == VOIDmode - || (GET_MODE_SIZE (outmode[j]) > GET_MODE_SIZE (inmode[j]))) - ? outmode[j] : inmode[j]); - - Insert extra parentheses so that Emacs will indent the code properly. -For example, the following indentation looks nice if you do it by hand, - - v = rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 - + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000; - -but Emacs would alter it. Adding a set of parentheses produces -something that looks equally nice, and which Emacs will preserve: - - v = (rup->ru_utime.tv_sec*1000 + rup->ru_utime.tv_usec/1000 - + rup->ru_stime.tv_sec*1000 + rup->ru_stime.tv_usec/1000); - - Format do-while statements like this: - - do - { - a = foo (a); - } - while (a > 0); - - Please use formfeed characters (control-L) to divide the program into -pages at logical places (but not within a function). It does not matter -just how long the pages are, since they do not have to fit on a printed -page. The formfeeds should appear alone on lines by themselves. - - -File: standards.info, Node: Comments, Next: Syntactic Conventions, Prev: Formatting, Up: Writing C - -5.2 Commenting Your Work -======================== - -Every program should start with a comment saying briefly what it is for. -Example: 'fmt - filter for simple filling of text'. This comment should -be at the top of the source file containing the 'main' function of the -program. - - Also, please write a brief comment at the start of each source file, -with the file name and a line or two about the overall purpose of the -file. - - Please write the comments in a GNU program in English, because -English is the one language that nearly all programmers in all countries -can read. If you do not write English well, please write comments in -English as well as you can, then ask other people to help rewrite them. -If you can't write comments in English, please find someone to work with -you and translate your comments into English. - - Please put a comment on each function saying what the function does, -what sorts of arguments it gets, and what the possible values of -arguments mean and are used for. It is not necessary to duplicate in -words the meaning of the C argument declarations, if a C type is being -used in its customary fashion. If there is anything nonstandard about -its use (such as an argument of type 'char *' which is really the -address of the second character of a string, not the first), or any -possible values that would not work the way one would expect (such as, -that strings containing newlines are not guaranteed to work), be sure to -say so. - - Also explain the significance of the return value, if there is one. - - Please put two spaces after the end of a sentence in your comments, -so that the Emacs sentence commands will work. Also, please write -complete sentences and capitalize the first word. If a lower-case -identifier comes at the beginning of a sentence, don't capitalize it! -Changing the spelling makes it a different identifier. If you don't -like starting a sentence with a lower case letter, write the sentence -differently (e.g., "The identifier lower-case is ..."). - - The comment on a function is much clearer if you use the argument -names to speak about the argument values. The variable name itself -should be lower case, but write it in upper case when you are speaking -about the value rather than the variable itself. Thus, "the inode -number NODE_NUM" rather than "an inode". - - There is usually no purpose in restating the name of the function in -the comment before it, because the reader can see that for himself. -There might be an exception when the comment is so long that the -function itself would be off the bottom of the screen. - - There should be a comment on each static variable as well, like this: - - /* Nonzero means truncate lines in the display; - zero means continue them. */ - int truncate_lines; - - Every '#endif' should have a comment, except in the case of short -conditionals (just a few lines) that are not nested. The comment should -state the condition of the conditional that is ending, _including its -sense_. '#else' should have a comment describing the condition _and -sense_ of the code that follows. For example: - - #ifdef foo - ... - #else /* not foo */ - ... - #endif /* not foo */ - #ifdef foo - ... - #endif /* foo */ - -but, by contrast, write the comments this way for a '#ifndef': - - #ifndef foo - ... - #else /* foo */ - ... - #endif /* foo */ - #ifndef foo - ... - #endif /* not foo */ - - -File: standards.info, Node: Syntactic Conventions, Next: Names, Prev: Comments, Up: Writing C - -5.3 Clean Use of C Constructs -============================= - -Please explicitly declare the types of all objects. For example, you -should explicitly declare all arguments to functions, and you should -declare functions to return 'int' rather than omitting the 'int'. - - Some programmers like to use the GCC '-Wall' option, and change the -code whenever it issues a warning. If you want to do this, then do. -Other programmers prefer not to use '-Wall', because it gives warnings -for valid and legitimate code which they do not want to change. If you -want to do this, then do. The compiler should be your servant, not your -master. - - Declarations of external functions and functions to appear later in -the source file should all go in one place near the beginning of the -file (somewhere before the first function definition in the file), or -else should go in a header file. Don't put 'extern' declarations inside -functions. - - It used to be common practice to use the same local variables (with -names like 'tem') over and over for different values within one -function. Instead of doing this, it is better to declare a separate -local variable for each distinct purpose, and give it a name which is -meaningful. This not only makes programs easier to understand, it also -facilitates optimization by good compilers. You can also move the -declaration of each local variable into the smallest scope that includes -all its uses. This makes the program even cleaner. - - Don't use local variables or parameters that shadow global -identifiers. - - Don't declare multiple variables in one declaration that spans lines. -Start a new declaration on each line, instead. For example, instead of -this: - - int foo, - bar; - -write either this: - - int foo, bar; - -or this: - - int foo; - int bar; - -(If they are global variables, each should have a comment preceding it -anyway.) - - When you have an 'if'-'else' statement nested in another 'if' -statement, always put braces around the 'if'-'else'. Thus, never write -like this: - - if (foo) - if (bar) - win (); - else - lose (); - -always like this: - - if (foo) - { - if (bar) - win (); - else - lose (); - } - - If you have an 'if' statement nested inside of an 'else' statement, -either write 'else if' on one line, like this, - - if (foo) - ... - else if (bar) - ... - -with its 'then'-part indented like the preceding 'then'-part, or write -the nested 'if' within braces like this: - - if (foo) - ... - else - { - if (bar) - ... - } - - Don't declare both a structure tag and variables or typedefs in the -same declaration. Instead, declare the structure tag separately and -then use it to declare the variables or typedefs. - - Try to avoid assignments inside 'if'-conditions (assignments inside -'while'-conditions are ok). For example, don't write this: - - if ((foo = (char *) malloc (sizeof *foo)) == 0) - fatal ("virtual memory exhausted"); - -instead, write this: - - foo = (char *) malloc (sizeof *foo); - if (foo == 0) - fatal ("virtual memory exhausted"); - - Don't make the program ugly to placate 'lint'. Please don't insert -any casts to 'void'. Zero without a cast is perfectly fine as a null -pointer constant, except when calling a varargs function. - - -File: standards.info, Node: Names, Next: System Portability, Prev: Syntactic Conventions, Up: Writing C - -5.4 Naming Variables, Functions, and Files -========================================== - -The names of global variables and functions in a program serve as -comments of a sort. So don't choose terse names--instead, look for -names that give useful information about the meaning of the variable or -function. In a GNU program, names should be English, like other -comments. - - Local variable names can be shorter, because they are used only -within one context, where (presumably) comments explain their purpose. - - Try to limit your use of abbreviations in symbol names. It is ok to -make a few abbreviations, explain what they mean, and then use them -frequently, but don't use lots of obscure abbreviations. - - Please use underscores to separate words in a name, so that the Emacs -word commands can be useful within them. Stick to lower case; reserve -upper case for macros and 'enum' constants, and for name-prefixes that -follow a uniform convention. - - For example, you should use names like 'ignore_space_change_flag'; -don't use names like 'iCantReadThis'. - - Variables that indicate whether command-line options have been -specified should be named after the meaning of the option, not after the -option-letter. A comment should state both the exact meaning of the -option and its letter. For example, - - /* Ignore changes in horizontal whitespace (-b). */ - int ignore_space_change_flag; - - When you want to define names with constant integer values, use -'enum' rather than '#define'. GDB knows about enumeration constants. - - You might want to make sure that none of the file names would -conflict if the files were loaded onto an MS-DOS file system which -shortens the names. You can use the program 'doschk' to test for this. - - Some GNU programs were designed to limit themselves to file names of -14 characters or less, to avoid file name conflicts if they are read -into older System V systems. Please preserve this feature in the -existing GNU programs that have it, but there is no need to do this in -new GNU programs. 'doschk' also reports file names longer than 14 -characters. - - -File: standards.info, Node: System Portability, Next: CPU Portability, Prev: Names, Up: Writing C - -5.5 Portability between System Types -==================================== - -In the Unix world, "portability" refers to porting to different Unix -versions. For a GNU program, this kind of portability is desirable, but -not paramount. - - The primary purpose of GNU software is to run on top of the GNU -kernel, compiled with the GNU C compiler, on various types of CPU. So -the kinds of portability that are absolutely necessary are quite -limited. But it is important to support Linux-based GNU systems, since -they are the form of GNU that is popular. - - Beyond that, it is good to support the other free operating systems -(*BSD), and it is nice to support other Unix-like systems if you want -to. Supporting a variety of Unix-like systems is desirable, although -not paramount. It is usually not too hard, so you may as well do it. -But you don't have to consider it an obligation, if it does turn out to -be hard. - - The easiest way to achieve portability to most Unix-like systems is -to use Autoconf. It's unlikely that your program needs to know more -information about the host platform than Autoconf can provide, simply -because most of the programs that need such knowledge have already been -written. - - Avoid using the format of semi-internal data bases (e.g., -directories) when there is a higher-level alternative ('readdir'). - - As for systems that are not like Unix, such as MSDOS, Windows, VMS, -MVS, and older Macintosh systems, supporting them is often a lot of -work. When that is the case, it is better to spend your time adding -features that will be useful on GNU and GNU/Linux, rather than on -supporting other incompatible systems. - - If you do support Windows, please do not abbreviate it as "win". In -hacker terminology, calling something a "win" is a form of praise. -You're free to praise Microsoft Windows on your own if you want, but -please don't do this in GNU packages. Instead of abbreviating "Windows" -to "win", you can write it in full or abbreviate it to "woe" or "w". In -GNU Emacs, for instance, we use 'w32' in file names of Windows-specific -files, but the macro for Windows conditionals is called 'WINDOWSNT'. - - It is a good idea to define the "feature test macro" '_GNU_SOURCE' -when compiling your C files. When you compile on GNU or GNU/Linux, this -will enable the declarations of GNU library extension functions, and -that will usually give you a compiler error message if you define the -same function names in some other way in your program. (You don't have -to actually _use_ these functions, if you prefer to make the program -more portable to other systems.) - - But whether or not you use these GNU extensions, you should avoid -using their names for any other meanings. Doing so would make it hard -to move your code into other GNU programs. - - -File: standards.info, Node: CPU Portability, Next: System Functions, Prev: System Portability, Up: Writing C - -5.6 Portability between CPUs -============================ - -Even GNU systems will differ because of differences among CPU types--for -example, difference in byte ordering and alignment requirements. It is -absolutely essential to handle these differences. However, don't make -any effort to cater to the possibility that an 'int' will be less than -32 bits. We don't support 16-bit machines in GNU. - - Similarly, don't make any effort to cater to the possibility that -'long' will be smaller than predefined types like 'size_t'. For -example, the following code is ok: - - printf ("size = %lu\n", (unsigned long) sizeof array); - printf ("diff = %ld\n", (long) (pointer2 - pointer1)); - - 1989 Standard C requires this to work, and we know of only one -counterexample: 64-bit programs on Microsoft Windows. We will leave it -to those who want to port GNU programs to that environment to figure out -how to do it. - - Predefined file-size types like 'off_t' are an exception: they are -longer than 'long' on many platforms, so code like the above won't work -with them. One way to print an 'off_t' value portably is to print its -digits yourself, one by one. - - Don't assume that the address of an 'int' object is also the address -of its least-significant byte. This is false on big-endian machines. -Thus, don't make the following mistake: - - int c; - ... - while ((c = getchar ()) != EOF) - write (file_descriptor, &c, 1); - -Instead, use 'unsigned char' as follows. (The 'unsigned' is for -portability to unusual systems where 'char' is signed and where there is -integer overflow checking.) - - int c; - while ((c = getchar ()) != EOF) - { - unsigned char u = c; - write (file_descriptor, &u, 1); - } - - It used to be ok to not worry about the difference between pointers -and integers when passing arguments to functions. However, on most -modern 64-bit machines pointers are wider than 'int'. Conversely, -integer types like 'long long int' and 'off_t' are wider than pointers -on most modern 32-bit machines. Hence it's often better nowadays to use -prototypes to define functions whose argument types are not trivial. - - In particular, if functions accept varying argument counts or types -they should be declared using prototypes containing '...' and defined -using 'stdarg.h'. For an example of this, please see the Gnulib -(http://www.gnu.org/software/gnulib/) error module, which declares and -defines the following function: - - /* Print a message with `fprintf (stderr, FORMAT, ...)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ - - void error (int status, int errnum, const char *format, ...); - - A simple way to use the Gnulib error module is to obtain the two -source files 'error.c' and 'error.h' from the Gnulib library source code -repository at . -Here's a sample use: - - #include "error.h" - #include - #include - - char *program_name = "myprogram"; - - FILE * - xfopen (char const *name) - { - FILE *fp = fopen (name, "r"); - if (! fp) - error (1, errno, "cannot read %s", name); - return fp; - } - - Avoid casting pointers to integers if you can. Such casts greatly -reduce portability, and in most programs they are easy to avoid. In the -cases where casting pointers to integers is essential--such as, a Lisp -interpreter which stores type information as well as an address in one -word--you'll have to make explicit provisions to handle different word -sizes. You will also need to make provision for systems in which the -normal range of addresses you can get from 'malloc' starts far away from -zero. - - -File: standards.info, Node: System Functions, Next: Internationalization, Prev: CPU Portability, Up: Writing C - -5.7 Calling System Functions -============================ - -C implementations differ substantially. Standard C reduces but does not -eliminate the incompatibilities; meanwhile, many GNU packages still -support pre-standard compilers because this is not hard to do. This -chapter gives recommendations for how to use the more-or-less standard C -library functions to avoid unnecessary loss of portability. - - * Don't use the return value of 'sprintf'. It returns the number of - characters written on some systems, but not on all systems. - - * Be aware that 'vfprintf' is not always available. - - * 'main' should be declared to return type 'int'. It should - terminate either by calling 'exit' or by returning the integer - status code; make sure it cannot ever return an undefined value. - - * Don't declare system functions explicitly. - - Almost any declaration for a system function is wrong on some - system. To minimize conflicts, leave it to the system header files - to declare system functions. If the headers don't declare a - function, let it remain undeclared. - - While it may seem unclean to use a function without declaring it, - in practice this works fine for most system library functions on - the systems where this really happens; thus, the disadvantage is - only theoretical. By contrast, actual declarations have frequently - caused actual conflicts. - - * If you must declare a system function, don't specify the argument - types. Use an old-style declaration, not a Standard C prototype. - The more you specify about the function, the more likely a - conflict. - - * In particular, don't unconditionally declare 'malloc' or 'realloc'. - - Most GNU programs use those functions just once, in functions - conventionally named 'xmalloc' and 'xrealloc'. These functions - call 'malloc' and 'realloc', respectively, and check the results. - - Because 'xmalloc' and 'xrealloc' are defined in your program, you - can declare them in other files without any risk of type conflict. - - On most systems, 'int' is the same length as a pointer; thus, the - calls to 'malloc' and 'realloc' work fine. For the few exceptional - systems (mostly 64-bit machines), you can use *conditionalized* - declarations of 'malloc' and 'realloc'--or put these declarations - in configuration files specific to those systems. - - * The string functions require special treatment. Some Unix systems - have a header file 'string.h'; others have 'strings.h'. Neither - file name is portable. There are two things you can do: use - Autoconf to figure out which file to include, or don't include - either file. - - * If you don't include either strings file, you can't get - declarations for the string functions from the header file in the - usual way. - - That causes less of a problem than you might think. The newer - standard string functions should be avoided anyway because many - systems still don't support them. The string functions you can use - are these: - - strcpy strncpy strcat strncat - strlen strcmp strncmp - strchr strrchr - - The copy and concatenate functions work fine without a declaration - as long as you don't use their values. Using their values without - a declaration fails on systems where the width of a pointer differs - from the width of 'int', and perhaps in other cases. It is trivial - to avoid using their values, so do that. - - The compare functions and 'strlen' work fine without a declaration - on most systems, possibly all the ones that GNU software runs on. - You may find it necessary to declare them *conditionally* on a few - systems. - - The search functions must be declared to return 'char *'. Luckily, - there is no variation in the data type they return. But there is - variation in their names. Some systems give these functions the - names 'index' and 'rindex'; other systems use the names 'strchr' - and 'strrchr'. Some systems support both pairs of names, but - neither pair works on all systems. - - You should pick a single pair of names and use it throughout your - program. (Nowadays, it is better to choose 'strchr' and 'strrchr' - for new programs, since those are the standard names.) Declare - both of those names as functions returning 'char *'. On systems - which don't support those names, define them as macros in terms of - the other pair. For example, here is what to put at the beginning - of your file (or in a header) if you want to use the names 'strchr' - and 'strrchr' throughout: - - #ifndef HAVE_STRCHR - #define strchr index - #endif - #ifndef HAVE_STRRCHR - #define strrchr rindex - #endif - - char *strchr (); - char *strrchr (); - - Here we assume that 'HAVE_STRCHR' and 'HAVE_STRRCHR' are macros -defined in systems where the corresponding functions exist. One way to -get them properly defined is to use Autoconf. - - -File: standards.info, Node: Internationalization, Next: Character Set, Prev: System Functions, Up: Writing C - -5.8 Internationalization -======================== - -GNU has a library called GNU gettext that makes it easy to translate the -messages in a program into various languages. You should use this -library in every program. Use English for the messages as they appear -in the program, and let gettext provide the way to translate them into -other languages. - - Using GNU gettext involves putting a call to the 'gettext' macro -around each string that might need translation--like this: - - printf (gettext ("Processing file `%s'...")); - -This permits GNU gettext to replace the string '"Processing file -`%s'..."' with a translated version. - - Once a program uses gettext, please make a point of writing calls to -'gettext' when you add new strings that call for translation. - - Using GNU gettext in a package involves specifying a "text domain -name" for the package. The text domain name is used to separate the -translations for this package from the translations for other packages. -Normally, the text domain name should be the same as the name of the -package--for example, 'coreutils' for the GNU core utilities. - - To enable gettext to work well, avoid writing code that makes -assumptions about the structure of words or sentences. When you want -the precise text of a sentence to vary depending on the data, use two or -more alternative string constants each containing a complete sentences, -rather than inserting conditionalized words or phrases into a single -sentence framework. - - Here is an example of what not to do: - - printf ("%s is full", capacity > 5000000 ? "disk" : "floppy disk"); - - If you apply gettext to all strings, like this, - - printf (gettext ("%s is full"), - capacity > 5000000 ? gettext ("disk") : gettext ("floppy disk")); - -the translator will hardly know that "disk" and "floppy disk" are meant -to be substituted in the other string. Worse, in some languages (like -French) the construction will not work: the translation of the word -"full" depends on the gender of the first part of the sentence; it -happens to be not the same for "disk" as for "floppy disk". - - Complete sentences can be translated without problems: - - printf (capacity > 5000000 ? gettext ("disk is full") - : gettext ("floppy disk is full")); - - A similar problem appears at the level of sentence structure with -this code: - - printf ("# Implicit rule search has%s been done.\n", - f->tried_implicit ? "" : " not"); - -Adding 'gettext' calls to this code cannot give correct results for all -languages, because negation in some languages requires adding words at -more than one place in the sentence. By contrast, adding 'gettext' -calls does the job straightforwardly if the code starts out like this: - - printf (f->tried_implicit - ? "# Implicit rule search has been done.\n", - : "# Implicit rule search has not been done.\n"); - - Another example is this one: - - printf ("%d file%s processed", nfiles, - nfiles != 1 ? "s" : ""); - -The problem with this example is that it assumes that plurals are made -by adding 's'. If you apply gettext to the format string, like this, - - printf (gettext ("%d file%s processed"), nfiles, - nfiles != 1 ? "s" : ""); - -the message can use different words, but it will still be forced to use -'s' for the plural. Here is a better way, with gettext being applied to -the two strings independently: - - printf ((nfiles != 1 ? gettext ("%d files processed") - : gettext ("%d file processed")), - nfiles); - -But this still doesn't work for languages like Polish, which has three -plural forms: one for nfiles == 1, one for nfiles == 2, 3, 4, 22, 23, -24, ... and one for the rest. The GNU 'ngettext' function solves this -problem: - - printf (ngettext ("%d files processed", "%d file processed", nfiles), - nfiles); - - -File: standards.info, Node: Character Set, Next: Quote Characters, Prev: Internationalization, Up: Writing C - -5.9 Character Set -================= - -Sticking to the ASCII character set (plain text, 7-bit characters) is -preferred in GNU source code comments, text documents, and other -contexts, unless there is good reason to do something else because of -the application domain. For example, if source code deals with the -French Revolutionary calendar, it is OK if its literal strings contain -accented characters in month names like "Flore'al". Also, it is OK to -use non-ASCII characters to represent proper names of contributors in -change logs (*note Change Logs::). - - If you need to use non-ASCII characters, you should normally stick -with one encoding, as one cannot in general mix encodings reliably. - - -File: standards.info, Node: Quote Characters, Next: Mmap, Prev: Character Set, Up: Writing C - -5.10 Quote Characters -===================== - -In the C locale, GNU programs should stick to plain ASCII for quotation -characters in messages to users: preferably 0x60 ('`') for left quotes -and 0x27 (''') for right quotes. It is ok, but not required, to use -locale-specific quotes in other locales. - - The Gnulib (http://www.gnu.org/software/gnulib/) 'quote' and -'quotearg' modules provide a reasonably straightforward way to support -locale-specific quote characters, as well as taking care of other -issues, such as quoting a filename that itself contains a quote -character. See the Gnulib documentation for usage details. - - In any case, the documentation for your program should clearly -specify how it does quoting, if different than the preferred method of -'`' and '''. This is especially important if the output of your program -is ever likely to be parsed by another program. - - Quotation characters are a difficult area in the computing world at -this time: there are no true left or right quote characters in Latin1; -the '`' character we use was standardized there as a grave accent. -Moreover, Latin1 is still not universally usable. - - Unicode contains the unambiguous quote characters required, and its -common encoding UTF-8 is upward compatible with Latin1. However, -Unicode and UTF-8 are not universally well-supported, either. - - This may change over the next few years, and then we will revisit -this. - - -File: standards.info, Node: Mmap, Prev: Quote Characters, Up: Writing C - -5.11 Mmap -========= - -Don't assume that 'mmap' either works on all files or fails for all -files. It may work on some files and fail on others. - - The proper way to use 'mmap' is to try it on the specific file for -which you want to use it--and if 'mmap' doesn't work, fall back on doing -the job in another way using 'read' and 'write'. - - The reason this precaution is needed is that the GNU kernel (the -HURD) provides a user-extensible file system, in which there can be many -different kinds of "ordinary files." Many of them support 'mmap', but -some do not. It is important to make programs handle all these kinds of -files. - - -File: standards.info, Node: Documentation, Next: Managing Releases, Prev: Writing C, Up: Top - -6 Documenting Programs -********************** - -A GNU program should ideally come with full free documentation, adequate -for both reference and tutorial purposes. If the package can be -programmed or extended, the documentation should cover programming or -extending it, as well as just using it. - -* Menu: - -* GNU Manuals:: Writing proper manuals. -* Doc Strings and Manuals:: Compiling doc strings doesn't make a manual. -* Manual Structure Details:: Specific structure conventions. -* License for Manuals:: Writing the distribution terms for a manual. -* Manual Credits:: Giving credit to documentation contributors. -* Printed Manuals:: Mentioning the printed manual. -* NEWS File:: NEWS files supplement manuals. -* Change Logs:: Recording changes. -* Man Pages:: Man pages are secondary. -* Reading other Manuals:: How far you can go in learning - from other manuals. - - -File: standards.info, Node: GNU Manuals, Next: Doc Strings and Manuals, Up: Documentation - -6.1 GNU Manuals -=============== - -The preferred document format for the GNU system is the Texinfo -formatting language. Every GNU package should (ideally) have -documentation in Texinfo both for reference and for learners. Texinfo -makes it possible to produce a good quality formatted book, using TeX, -and to generate an Info file. It is also possible to generate HTML -output from Texinfo source. See the Texinfo manual, either the -hardcopy, or the on-line version available through 'info' or the Emacs -Info subsystem ('C-h i'). - - Nowadays some other formats such as Docbook and Sgmltexi can be -converted automatically into Texinfo. It is ok to produce the Texinfo -documentation by conversion this way, as long as it gives good results. - - Make sure your manual is clear to a reader who knows nothing about -the topic and reads it straight through. This means covering basic -topics at the beginning, and advanced topics only later. This also -means defining every specialized term when it is first used. - - Programmers tend to carry over the structure of the program as the -structure for its documentation. But this structure is not necessarily -good for explaining how to use the program; it may be irrelevant and -confusing for a user. - - Instead, the right way to structure documentation is according to the -concepts and questions that a user will have in mind when reading it. -This principle applies at every level, from the lowest (ordering -sentences in a paragraph) to the highest (ordering of chapter topics -within the manual). Sometimes this structure of ideas matches the -structure of the implementation of the software being documented--but -often they are different. An important part of learning to write good -documentation is to learn to notice when you have unthinkingly -structured the documentation like the implementation, stop yourself, and -look for better alternatives. - - For example, each program in the GNU system probably ought to be -documented in one manual; but this does not mean each program should -have its own manual. That would be following the structure of the -implementation, rather than the structure that helps the user -understand. - - Instead, each manual should cover a coherent _topic_. For example, -instead of a manual for 'diff' and a manual for 'diff3', we have one -manual for "comparison of files" which covers both of those programs, as -well as 'cmp'. By documenting these programs together, we can make the -whole subject clearer. - - The manual which discusses a program should certainly document all of -the program's command-line options and all of its commands. It should -give examples of their use. But don't organize the manual as a list of -features. Instead, organize it logically, by subtopics. Address the -questions that a user will ask when thinking about the job that the -program does. Don't just tell the reader what each feature can do--say -what jobs it is good for, and show how to use it for those jobs. -Explain what is recommended usage, and what kinds of usage users should -avoid. - - In general, a GNU manual should serve both as tutorial and reference. -It should be set up for convenient access to each topic through Info, -and for reading straight through (appendixes aside). A GNU manual -should give a good introduction to a beginner reading through from the -start, and should also provide all the details that hackers want. The -Bison manual is a good example of this--please take a look at it to see -what we mean. - - That is not as hard as it first sounds. Arrange each chapter as a -logical breakdown of its topic, but order the sections, and write their -text, so that reading the chapter straight through makes sense. Do -likewise when structuring the book into chapters, and when structuring a -section into paragraphs. The watchword is, _at each point, address the -most fundamental and important issue raised by the preceding text._ - - If necessary, add extra chapters at the beginning of the manual which -are purely tutorial and cover the basics of the subject. These provide -the framework for a beginner to understand the rest of the manual. The -Bison manual provides a good example of how to do this. - - To serve as a reference, a manual should have an Index that list all -the functions, variables, options, and important concepts that are part -of the program. One combined Index should do for a short manual, but -sometimes for a complex package it is better to use multiple indices. -The Texinfo manual includes advice on preparing good index entries, see -*note Making Index Entries: (texinfo)Index Entries, and see *note -Defining the Entries of an Index: (texinfo)Indexing Commands. - - Don't use Unix man pages as a model for how to write GNU -documentation; most of them are terse, badly structured, and give -inadequate explanation of the underlying concepts. (There are, of -course, some exceptions.) Also, Unix man pages use a particular format -which is different from what we use in GNU manuals. - - Please include an email address in the manual for where to report -bugs _in the text of the manual_. - - Please do not use the term "pathname" that is used in Unix -documentation; use "file name" (two words) instead. We use the term -"path" only for search paths, which are lists of directory names. - - Please do not use the term "illegal" to refer to erroneous input to a -computer program. Please use "invalid" for this, and reserve the term -"illegal" for activities prohibited by law. - - Please do not write '()' after a function name just to indicate it is -a function. 'foo ()' is not a function, it is a function call with no -arguments. - - -File: standards.info, Node: Doc Strings and Manuals, Next: Manual Structure Details, Prev: GNU Manuals, Up: Documentation - -6.2 Doc Strings and Manuals -=========================== - -Some programming systems, such as Emacs, provide a documentation string -for each function, command or variable. You may be tempted to write a -reference manual by compiling the documentation strings and writing a -little additional text to go around them--but you must not do it. That -approach is a fundamental mistake. The text of well-written -documentation strings will be entirely wrong for a manual. - - A documentation string needs to stand alone--when it appears on the -screen, there will be no other text to introduce or explain it. -Meanwhile, it can be rather informal in style. - - The text describing a function or variable in a manual must not stand -alone; it appears in the context of a section or subsection. Other text -at the beginning of the section should explain some of the concepts, and -should often make some general points that apply to several functions or -variables. The previous descriptions of functions and variables in the -section will also have given information about the topic. A description -written to stand alone would repeat some of that information; this -redundancy looks bad. Meanwhile, the informality that is acceptable in -a documentation string is totally unacceptable in a manual. - - The only good way to use documentation strings in writing a good -manual is to use them as a source of information for writing good text. - - -File: standards.info, Node: Manual Structure Details, Next: License for Manuals, Prev: Doc Strings and Manuals, Up: Documentation - -6.3 Manual Structure Details -============================ - -The title page of the manual should state the version of the programs or -packages documented in the manual. The Top node of the manual should -also contain this information. If the manual is changing more -frequently than or independent of the program, also state a version -number for the manual in both of these places. - - Each program documented in the manual should have a node named -'PROGRAM Invocation' or 'Invoking PROGRAM'. This node (together with -its subnodes, if any) should describe the program's command line -arguments and how to run it (the sort of information people would look -for in a man page). Start with an '@example' containing a template for -all the options and arguments that the program uses. - - Alternatively, put a menu item in some menu whose item name fits one -of the above patterns. This identifies the node which that item points -to as the node for this purpose, regardless of the node's actual name. - - The '--usage' feature of the Info reader looks for such a node or -menu item in order to find the relevant text, so it is essential for -every Texinfo file to have one. - - If one manual describes several programs, it should have such a node -for each program described in the manual. - - -File: standards.info, Node: License for Manuals, Next: Manual Credits, Prev: Manual Structure Details, Up: Documentation - -6.4 License for Manuals -======================= - -Please use the GNU Free Documentation License for all GNU manuals that -are more than a few pages long. Likewise for a collection of short -documents--you only need one copy of the GNU FDL for the whole -collection. For a single short document, you can use a very permissive -non-copyleft license, to avoid taking up space with a long license. - - See for more explanation -of how to employ the GFDL. - - Note that it is not obligatory to include a copy of the GNU GPL or -GNU LGPL in a manual whose license is neither the GPL nor the LGPL. It -can be a good idea to include the program's license in a large manual; -in a short manual, whose size would be increased considerably by -including the program's license, it is probably better not to include -it. - - -File: standards.info, Node: Manual Credits, Next: Printed Manuals, Prev: License for Manuals, Up: Documentation - -6.5 Manual Credits -================== - -Please credit the principal human writers of the manual as the authors, -on the title page of the manual. If a company sponsored the work, thank -the company in a suitable place in the manual, but do not cite the -company as an author. - - -File: standards.info, Node: Printed Manuals, Next: NEWS File, Prev: Manual Credits, Up: Documentation - -6.6 Printed Manuals -=================== - -The FSF publishes some GNU manuals in printed form. To encourage sales -of these manuals, the on-line versions of the manual should mention at -the very start that the printed manual is available and should point at -information for getting it--for instance, with a link to the page -. This should not be included in -the printed manual, though, because there it is redundant. - - It is also useful to explain in the on-line forms of the manual how -the user can print out the manual from the sources. - - -File: standards.info, Node: NEWS File, Next: Change Logs, Prev: Printed Manuals, Up: Documentation - -6.7 The NEWS File -================= - -In addition to its manual, the package should have a file named 'NEWS' -which contains a list of user-visible changes worth mentioning. In each -new release, add items to the front of the file and identify the version -they pertain to. Don't discard old items; leave them in the file after -the newer items. This way, a user upgrading from any previous version -can see what is new. - - If the 'NEWS' file gets very long, move some of the older items into -a file named 'ONEWS' and put a note at the end referring the user to -that file. - - -File: standards.info, Node: Change Logs, Next: Man Pages, Prev: NEWS File, Up: Documentation - -6.8 Change Logs -=============== - -Keep a change log to describe all the changes made to program source -files. The purpose of this is so that people investigating bugs in the -future will know about the changes that might have introduced the bug. -Often a new bug can be found by looking at what was recently changed. -More importantly, change logs can help you eliminate conceptual -inconsistencies between different parts of a program, by giving you a -history of how the conflicting concepts arose and who they came from. - -* Menu: - -* Change Log Concepts:: -* Style of Change Logs:: -* Simple Changes:: -* Conditional Changes:: -* Indicating the Part Changed:: - - -File: standards.info, Node: Change Log Concepts, Next: Style of Change Logs, Up: Change Logs - -6.8.1 Change Log Concepts -------------------------- - -You can think of the change log as a conceptual "undo list" which -explains how earlier versions were different from the current version. -People can see the current version; they don't need the change log to -tell them what is in it. What they want from a change log is a clear -explanation of how the earlier version differed. - - The change log file is normally called 'ChangeLog' and covers an -entire directory. Each directory can have its own change log, or a -directory can use the change log of its parent directory--it's up to -you. - - Another alternative is to record change log information with a -version control system such as RCS or CVS. This can be converted -automatically to a 'ChangeLog' file using 'rcs2log'; in Emacs, the -command 'C-x v a' ('vc-update-change-log') does the job. - - There's no need to describe the full purpose of the changes or how -they work together. However, sometimes it is useful to write one line -to describe the overall purpose of a change or a batch of changes. If -you think that a change calls for explanation, you're probably right. -Please do explain it--but please put the full explanation in comments in -the code, where people will see it whenever they see the code. For -example, "New function" is enough for the change log when you add a -function, because there should be a comment before the function -definition to explain what it does. - - In the past, we recommended not mentioning changes in non-software -files (manuals, help files, etc.) in change logs. However, we've been -advised that it is a good idea to include them, for the sake of -copyright records. - - The easiest way to add an entry to 'ChangeLog' is with the Emacs -command 'M-x add-change-log-entry'. An entry should have an asterisk, -the name of the changed file, and then in parentheses the name of the -changed functions, variables or whatever, followed by a colon. Then -describe the changes you made to that function or variable. - - -File: standards.info, Node: Style of Change Logs, Next: Simple Changes, Prev: Change Log Concepts, Up: Change Logs - -6.8.2 Style of Change Logs --------------------------- - -Here are some simple examples of change log entries, starting with the -header line that says who made the change and when it was installed, -followed by descriptions of specific changes. (These examples are drawn -from Emacs and GCC.) - - 1998-08-17 Richard Stallman - - * register.el (insert-register): Return nil. - (jump-to-register): Likewise. - - * sort.el (sort-subr): Return nil. - - * tex-mode.el (tex-bibtex-file, tex-file, tex-region): - Restart the tex shell if process is gone or stopped. - (tex-shell-running): New function. - - * expr.c (store_one_arg): Round size up for move_block_to_reg. - (expand_call): Round up when emitting USE insns. - * stmt.c (assign_parms): Round size up for move_block_from_reg. - - It's important to name the changed function or variable in full. -Don't abbreviate function or variable names, and don't combine them. -Subsequent maintainers will often search for a function name to find all -the change log entries that pertain to it; if you abbreviate the name, -they won't find it when they search. - - For example, some people are tempted to abbreviate groups of function -names by writing '* register.el ({insert,jump-to}-register)'; this is -not a good idea, since searching for 'jump-to-register' or -'insert-register' would not find that entry. - - Separate unrelated change log entries with blank lines. When two -entries represent parts of the same change, so that they work together, -then don't put blank lines between them. Then you can omit the file -name and the asterisk when successive entries are in the same file. - - Break long lists of function names by closing continued lines with -')', rather than ',', and opening the continuation with '(' as in this -example: - - * keyboard.c (menu_bar_items, tool_bar_items) - (Fexecute_extended_command): Deal with `keymap' property. - - When you install someone else's changes, put the contributor's name -in the change log entry rather than in the text of the entry. In other -words, write this: - - 2002-07-14 John Doe - - * sewing.c: Make it sew. - -rather than this: - - 2002-07-14 Usual Maintainer - - * sewing.c: Make it sew. Patch by jdoe@gnu.org. - - As for the date, that should be the date you applied the change. - - -File: standards.info, Node: Simple Changes, Next: Conditional Changes, Prev: Style of Change Logs, Up: Change Logs - -6.8.3 Simple Changes --------------------- - -Certain simple kinds of changes don't need much detail in the change -log. - - When you change the calling sequence of a function in a simple -fashion, and you change all the callers of the function to use the new -calling sequence, there is no need to make individual entries for all -the callers that you changed. Just write in the entry for the function -being called, "All callers changed"--like this: - - * keyboard.c (Fcommand_execute): New arg SPECIAL. - All callers changed. - - When you change just comments or doc strings, it is enough to write -an entry for the file, without mentioning the functions. Just "Doc -fixes" is enough for the change log. - - There's no technical need to make change log entries for -documentation files. This is because documentation is not susceptible -to bugs that are hard to fix. Documentation does not consist of parts -that must interact in a precisely engineered fashion. To correct an -error, you need not know the history of the erroneous passage; it is -enough to compare what the documentation says with the way the program -actually works. - - However, you should keep change logs for documentation files when the -project gets copyright assignments from its contributors, so as to make -the records of authorship more accurate. - - -File: standards.info, Node: Conditional Changes, Next: Indicating the Part Changed, Prev: Simple Changes, Up: Change Logs - -6.8.4 Conditional Changes -------------------------- - -C programs often contain compile-time '#if' conditionals. Many changes -are conditional; sometimes you add a new definition which is entirely -contained in a conditional. It is very useful to indicate in the change -log the conditions for which the change applies. - - Our convention for indicating conditional changes is to use square -brackets around the name of the condition. - - Here is a simple example, describing a change which is conditional -but does not have a function or entity name associated with it: - - * xterm.c [SOLARIS2]: Include string.h. - - Here is an entry describing a new definition which is entirely -conditional. This new definition for the macro 'FRAME_WINDOW_P' is used -only when 'HAVE_X_WINDOWS' is defined: - - * frame.h [HAVE_X_WINDOWS] (FRAME_WINDOW_P): Macro defined. - - Here is an entry for a change within the function 'init_display', -whose definition as a whole is unconditional, but the changes themselves -are contained in a '#ifdef HAVE_LIBNCURSES' conditional: - - * dispnew.c (init_display) [HAVE_LIBNCURSES]: If X, call tgetent. - - Here is an entry for a change that takes affect only when a certain -macro is _not_ defined: - - (gethostname) [!HAVE_SOCKETS]: Replace with winsock version. - - -File: standards.info, Node: Indicating the Part Changed, Prev: Conditional Changes, Up: Change Logs - -6.8.5 Indicating the Part Changed ---------------------------------- - -Indicate the part of a function which changed by using angle brackets -enclosing an indication of what the changed part does. Here is an entry -for a change in the part of the function 'sh-while-getopts' that deals -with 'sh' commands: - - * progmodes/sh-script.el (sh-while-getopts) : Handle case that - user-specified option string is empty. - - -File: standards.info, Node: Man Pages, Next: Reading other Manuals, Prev: Change Logs, Up: Documentation - -6.9 Man Pages -============= - -In the GNU project, man pages are secondary. It is not necessary or -expected for every GNU program to have a man page, but some of them do. -It's your choice whether to include a man page in your program. - - When you make this decision, consider that supporting a man page -requires continual effort each time the program is changed. The time -you spend on the man page is time taken away from more useful work. - - For a simple program which changes little, updating the man page may -be a small job. Then there is little reason not to include a man page, -if you have one. - - For a large program that changes a great deal, updating a man page -may be a substantial burden. If a user offers to donate a man page, you -may find this gift costly to accept. It may be better to refuse the man -page unless the same person agrees to take full responsibility for -maintaining it--so that you can wash your hands of it entirely. If this -volunteer later ceases to do the job, then don't feel obliged to pick it -up yourself; it may be better to withdraw the man page from the -distribution until someone else agrees to update it. - - When a program changes only a little, you may feel that the -discrepancies are small enough that the man page remains useful without -updating. If so, put a prominent note near the beginning of the man -page explaining that you don't maintain it and that the Texinfo manual -is more authoritative. The note should say how to access the Texinfo -documentation. - - Be sure that man pages include a copyright statement and free -license. The simple all-permissive license is appropriate for simple -man pages (*note (maintain)License Notices for Other Files::). - - For long man pages, with enough explanation and documentation that -they can be considered true manuals, use the GFDL (*note License for -Manuals::). - - Finally, the GNU help2man program -() is one way to automate -generation of a man page, in this case from '--help' output. This is -sufficient in many cases. - - -File: standards.info, Node: Reading other Manuals, Prev: Man Pages, Up: Documentation - -6.10 Reading other Manuals -========================== - -There may be non-free books or documentation files that describe the -program you are documenting. - - It is ok to use these documents for reference, just as the author of -a new algebra textbook can read other books on algebra. A large portion -of any non-fiction book consists of facts, in this case facts about how -a certain program works, and these facts are necessarily the same for -everyone who writes about the subject. But be careful not to copy your -outline structure, wording, tables or examples from preexisting non-free -documentation. Copying from free documentation may be ok; please check -with the FSF about the individual case. - - -File: standards.info, Node: Managing Releases, Next: References, Prev: Documentation, Up: Top - -7 The Release Process -********************* - -Making a release is more than just bundling up your source files in a -tar file and putting it up for FTP. You should set up your software so -that it can be configured to run on a variety of systems. Your Makefile -should conform to the GNU standards described below, and your directory -layout should also conform to the standards discussed below. Doing so -makes it easy to include your package into the larger framework of all -GNU software. - -* Menu: - -* Configuration:: How configuration of GNU packages should work. -* Makefile Conventions:: Makefile conventions. -* Releases:: Making releases - - -File: standards.info, Node: Configuration, Next: Makefile Conventions, Up: Managing Releases - -7.1 How Configuration Should Work -================================= - -Each GNU distribution should come with a shell script named 'configure'. -This script is given arguments which describe the kind of machine and -system you want to compile the program for. The 'configure' script must -record the configuration options so that they affect compilation. - - The description here is the specification of the interface for the -'configure' script in GNU packages. Many packages implement it using -GNU Autoconf (*note Introduction: (autoconf)Top.) and/or GNU Automake -(*note Introduction: (automake)Top.), but you do not have to use these -tools. You can implement it any way you like; for instance, by making -'configure' be a wrapper around a completely different configuration -system. - - Another way for the 'configure' script to operate is to make a link -from a standard name such as 'config.h' to the proper configuration file -for the chosen system. If you use this technique, the distribution -should _not_ contain a file named 'config.h'. This is so that people -won't be able to build the program without configuring it first. - - Another thing that 'configure' can do is to edit the Makefile. If -you do this, the distribution should _not_ contain a file named -'Makefile'. Instead, it should include a file 'Makefile.in' which -contains the input used for editing. Once again, this is so that people -won't be able to build the program without configuring it first. - - If 'configure' does write the 'Makefile', then 'Makefile' should have -a target named 'Makefile' which causes 'configure' to be rerun, setting -up the same configuration that was set up last time. The files that -'configure' reads should be listed as dependencies of 'Makefile'. - - All the files which are output from the 'configure' script should -have comments at the beginning explaining that they were generated -automatically using 'configure'. This is so that users won't think of -trying to edit them by hand. - - The 'configure' script should write a file named 'config.status' -which describes which configuration options were specified when the -program was last configured. This file should be a shell script which, -if run, will recreate the same configuration. - - The 'configure' script should accept an option of the form -'--srcdir=DIRNAME' to specify the directory where sources are found (if -it is not the current directory). This makes it possible to build the -program in a separate directory, so that the actual source directory is -not modified. - - If the user does not specify '--srcdir', then 'configure' should -check both '.' and '..' to see if it can find the sources. If it finds -the sources in one of these places, it should use them from there. -Otherwise, it should report that it cannot find the sources, and should -exit with nonzero status. - - Usually the easy way to support '--srcdir' is by editing a definition -of 'VPATH' into the Makefile. Some rules may need to refer explicitly -to the specified source directory. To make this possible, 'configure' -can add to the Makefile a variable named 'srcdir' whose value is -precisely the specified directory. - - In addition, the 'configure' script should take options corresponding -to most of the standard directory variables (*note Directory -Variables::). Here is the list: - - --prefix --exec-prefix --bindir --sbindir --libexecdir --sysconfdir - --sharedstatedir --localstatedir --libdir --includedir --oldincludedir - --datarootdir --datadir --infodir --localedir --mandir --docdir - --htmldir --dvidir --pdfdir --psdir - - The 'configure' script should also take an argument which specifies -the type of system to build the program for. This argument should look -like this: - - CPU-COMPANY-SYSTEM - - For example, an Athlon-based GNU/Linux system might be -'i686-pc-linux-gnu'. - - The 'configure' script needs to be able to decode all plausible -alternatives for how to describe a machine. Thus, 'athlon-pc-gnu/linux' -would be a valid alias. There is a shell script called 'config.sub' -(http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD) -that you can use as a subroutine to validate system types and -canonicalize aliases. - - The 'configure' script should also take the option -'--build=BUILDTYPE', which should be equivalent to a plain BUILDTYPE -argument. For example, 'configure --build=i686-pc-linux-gnu' is -equivalent to 'configure i686-pc-linux-gnu'. When the build type is not -specified by an option or argument, the 'configure' script should -normally guess it using the shell script 'config.guess' -(http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD). - - Other options are permitted to specify in more detail the software or -hardware present on the machine, to include or exclude optional parts of -the package, or to adjust the name of some tools or arguments to them: - -'--enable-FEATURE[=PARAMETER]' - Configure the package to build and install an optional user-level - facility called FEATURE. This allows users to choose which - optional features to include. Giving an optional PARAMETER of 'no' - should omit FEATURE, if it is built by default. - - No '--enable' option should *ever* cause one feature to replace - another. No '--enable' option should ever substitute one useful - behavior for another useful behavior. The only proper use for - '--enable' is for questions of whether to build part of the program - or exclude it. - -'--with-PACKAGE' - The package PACKAGE will be installed, so configure this package to - work with PACKAGE. - - Possible values of PACKAGE include 'gnu-as' (or 'gas'), 'gnu-ld', - 'gnu-libc', 'gdb', 'x', and 'x-toolkit'. - - Do not use a '--with' option to specify the file name to use to - find certain files. That is outside the scope of what '--with' - options are for. - -'VARIABLE=VALUE' - Set the value of the variable VARIABLE to VALUE. This is used to - override the default values of commands or arguments in the build - process. For example, the user could issue 'configure CFLAGS=-g - CXXFLAGS=-g' to build with debugging information and without the - default optimization. - - Specifying variables as arguments to 'configure', like this: - ./configure CC=gcc - is preferable to setting them in environment variables: - CC=gcc ./configure - as it helps to recreate the same configuration later with - 'config.status'. However, both methods should be supported. - - All 'configure' scripts should accept all of the "detail" options and -the variable settings, whether or not they make any difference to the -particular package at hand. In particular, they should accept any -option that starts with '--with-' or '--enable-'. This is so users will -be able to configure an entire GNU source tree at once with a single set -of options. - - You will note that the categories '--with-' and '--enable-' are -narrow: they *do not* provide a place for any sort of option you might -think of. That is deliberate. We want to limit the possible -configuration options in GNU software. We do not want GNU programs to -have idiosyncratic configuration options. - - Packages that perform part of the compilation process may support -cross-compilation. In such a case, the host and target machines for the -program may be different. - - The 'configure' script should normally treat the specified type of -system as both the host and the target, thus producing a program which -works for the same type of machine that it runs on. - - To compile a program to run on a host type that differs from the -build type, use the configure option '--host=HOSTTYPE', where HOSTTYPE -uses the same syntax as BUILDTYPE. The host type normally defaults to -the build type. - - To configure a cross-compiler, cross-assembler, or what have you, you -should specify a target different from the host, using the configure -option '--target=TARGETTYPE'. The syntax for TARGETTYPE is the same as -for the host type. So the command would look like this: - - ./configure --host=HOSTTYPE --target=TARGETTYPE - - The target type normally defaults to the host type. Programs for -which cross-operation is not meaningful need not accept the '--target' -option, because configuring an entire operating system for -cross-operation is not a meaningful operation. - - Some programs have ways of configuring themselves automatically. If -your program is set up to do this, your 'configure' script can simply -ignore most of its arguments. - - -File: standards.info, Node: Makefile Conventions, Next: Releases, Prev: Configuration, Up: Managing Releases - -7.2 Makefile Conventions -======================== - -This node describes conventions for writing the Makefiles for GNU -programs. Using Automake will help you write a Makefile that follows -these conventions. - -* Menu: - -* Makefile Basics:: General conventions for Makefiles. -* Utilities in Makefiles:: Utilities to be used in Makefiles. -* Command Variables:: Variables for specifying commands. -* DESTDIR:: Supporting staged installs. -* Directory Variables:: Variables for installation directories. -* Standard Targets:: Standard targets for users. -* Install Command Categories:: Three categories of commands in the 'install' - rule: normal, pre-install and post-install. - - -File: standards.info, Node: Makefile Basics, Next: Utilities in Makefiles, Up: Makefile Conventions - -7.2.1 General Conventions for Makefiles ---------------------------------------- - -Every Makefile should contain this line: - - SHELL = /bin/sh - -to avoid trouble on systems where the 'SHELL' variable might be -inherited from the environment. (This is never a problem with GNU -'make'.) - - Different 'make' programs have incompatible suffix lists and implicit -rules, and this sometimes creates confusion or misbehavior. So it is a -good idea to set the suffix list explicitly using only the suffixes you -need in the particular Makefile, like this: - - .SUFFIXES: - .SUFFIXES: .c .o - -The first line clears out the suffix list, the second introduces all -suffixes which may be subject to implicit rules in this Makefile. - - Don't assume that '.' is in the path for command execution. When you -need to run programs that are a part of your package during the make, -please make sure that it uses './' if the program is built as part of -the make or '$(srcdir)/' if the file is an unchanging part of the source -code. Without one of these prefixes, the current search path is used. - - The distinction between './' (the "build directory") and '$(srcdir)/' -(the "source directory") is important because users can build in a -separate directory using the '--srcdir' option to 'configure'. A rule -of the form: - - foo.1 : foo.man sedscript - sed -e sedscript foo.man > foo.1 - -will fail when the build directory is not the source directory, because -'foo.man' and 'sedscript' are in the source directory. - - When using GNU 'make', relying on 'VPATH' to find the source file -will work in the case where there is a single dependency file, since the -'make' automatic variable '$<' will represent the source file wherever -it is. (Many versions of 'make' set '$<' only in implicit rules.) A -Makefile target like - - foo.o : bar.c - $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o - -should instead be written as - - foo.o : bar.c - $(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@ - -in order to allow 'VPATH' to work correctly. When the target has -multiple dependencies, using an explicit '$(srcdir)' is the easiest way -to make the rule work well. For example, the target above for 'foo.1' -is best written as: - - foo.1 : foo.man sedscript - sed -e $(srcdir)/sedscript $(srcdir)/foo.man > $@ - - GNU distributions usually contain some files which are not source -files--for example, Info files, and the output from Autoconf, Automake, -Bison or Flex. Since these files normally appear in the source -directory, they should always appear in the source directory, not in the -build directory. So Makefile rules to update them should put the -updated files in the source directory. - - However, if a file does not appear in the distribution, then the -Makefile should not put it in the source directory, because building a -program in ordinary circumstances should not modify the source directory -in any way. - - Try to make the build and installation targets, at least (and all -their subtargets) work correctly with a parallel 'make'. - - -File: standards.info, Node: Utilities in Makefiles, Next: Command Variables, Prev: Makefile Basics, Up: Makefile Conventions - -7.2.2 Utilities in Makefiles ----------------------------- - -Write the Makefile commands (and any shell scripts, such as 'configure') -to run in 'sh', not in 'csh'. Don't use any special features of 'ksh' -or 'bash'. - - The 'configure' script and the Makefile rules for building and -installation should not use any utilities directly except these: - - cat cmp cp diff echo egrep expr false grep install-info - ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true - - The compression program 'gzip' can be used in the 'dist' rule. - - Stick to the generally supported options for these programs. For -example, don't use 'mkdir -p', convenient as it may be, because most -systems don't support it. - - It is a good idea to avoid creating symbolic links in makefiles, -since a few systems don't support them. - - The Makefile rules for building and installation can also use -compilers and related programs, but should do so via 'make' variables so -that the user can substitute alternatives. Here are some of the -programs we mean: - - ar bison cc flex install ld ldconfig lex - make makeinfo ranlib texi2dvi yacc - - Use the following 'make' variables to run those programs: - - $(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX) - $(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC) - - When you use 'ranlib' or 'ldconfig', you should make sure nothing bad -happens if the system does not have the program in question. Arrange to -ignore an error from that command, and print a message before the -command to tell the user that failure of this command does not mean a -problem. (The Autoconf 'AC_PROG_RANLIB' macro can help with this.) - - If you use symbolic links, you should implement a fallback for -systems that don't have symbolic links. - - Additional utilities that can be used via Make variables are: - - chgrp chmod chown mknod - - It is ok to use other utilities in Makefile portions (or scripts) -intended only for particular systems where you know those utilities -exist. - - -File: standards.info, Node: Command Variables, Next: DESTDIR, Prev: Utilities in Makefiles, Up: Makefile Conventions - -7.2.3 Variables for Specifying Commands ---------------------------------------- - -Makefiles should provide variables for overriding certain commands, -options, and so on. - - In particular, you should run most utility programs via variables. -Thus, if you use Bison, have a variable named 'BISON' whose default -value is set with 'BISON = bison', and refer to it with '$(BISON)' -whenever you need to use Bison. - - File management utilities such as 'ln', 'rm', 'mv', and so on, need -not be referred to through variables in this way, since users don't need -to replace them with other programs. - - Each program-name variable should come with an options variable that -is used to supply options to the program. Append 'FLAGS' to the -program-name variable name to get the options variable name--for -example, 'BISONFLAGS'. (The names 'CFLAGS' for the C compiler, 'YFLAGS' -for yacc, and 'LFLAGS' for lex, are exceptions to this rule, but we keep -them because they are standard.) Use 'CPPFLAGS' in any compilation -command that runs the preprocessor, and use 'LDFLAGS' in any compilation -command that does linking as well as in any direct use of 'ld'. - - If there are C compiler options that _must_ be used for proper -compilation of certain files, do not include them in 'CFLAGS'. Users -expect to be able to specify 'CFLAGS' freely themselves. Instead, -arrange to pass the necessary options to the C compiler independently of -'CFLAGS', by writing them explicitly in the compilation commands or by -defining an implicit rule, like this: - - CFLAGS = -g - ALL_CFLAGS = -I. $(CFLAGS) - .c.o: - $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< - - Do include the '-g' option in 'CFLAGS', because that is not -_required_ for proper compilation. You can consider it a default that -is only recommended. If the package is set up so that it is compiled -with GCC by default, then you might as well include '-O' in the default -value of 'CFLAGS' as well. - - Put 'CFLAGS' last in the compilation command, after other variables -containing compiler options, so the user can use 'CFLAGS' to override -the others. - - 'CFLAGS' should be used in every invocation of the C compiler, both -those which do compilation and those which do linking. - - Every Makefile should define the variable 'INSTALL', which is the -basic command for installing a file into the system. - - Every Makefile should also define the variables 'INSTALL_PROGRAM' and -'INSTALL_DATA'. (The default for 'INSTALL_PROGRAM' should be -'$(INSTALL)'; the default for 'INSTALL_DATA' should be '${INSTALL} -m -644'.) Then it should use those variables as the commands for actual -installation, for executables and non-executables respectively. Minimal -use of these variables is as follows: - - $(INSTALL_PROGRAM) foo $(bindir)/foo - $(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a - - However, it is preferable to support a 'DESTDIR' prefix on the target -files, as explained in the next section. - -Always use a file name, not a directory name, as the second argument of -the installation commands. Use a separate command for each file to be -installed. - - -File: standards.info, Node: DESTDIR, Next: Directory Variables, Prev: Command Variables, Up: Makefile Conventions - -7.2.4 'DESTDIR': support for staged installs --------------------------------------------- - -'DESTDIR' is a variable prepended to each installed target file, like -this: - - $(INSTALL_PROGRAM) foo $(DESTDIR)$(bindir)/foo - $(INSTALL_DATA) libfoo.a $(DESTDIR)$(libdir)/libfoo.a - - The 'DESTDIR' variable is specified by the user on the 'make' command -line. For example: - - make DESTDIR=/tmp/stage install - -'DESTDIR' should be supported only in the 'install*' and 'uninstall*' -targets, as those are the only targets where it is useful. - - If your installation step would normally install '/usr/local/bin/foo' -and '/usr/local/lib/libfoo.a', then an installation invoked as in the -example above would install '/tmp/stage/usr/local/bin/foo' and -'/tmp/stage/usr/local/lib/libfoo.a' instead. - - Prepending the variable 'DESTDIR' to each target in this way provides -for "staged installs", where the installed files are not placed directly -into their expected location but are instead copied into a temporary -location ('DESTDIR'). However, installed files maintain their relative -directory structure and any embedded file names will not be modified. - - You should not set the value of 'DESTDIR' in your 'Makefile' at all; -then the files are installed into their expected locations by default. -Also, specifying 'DESTDIR' should not change the operation of the -software in any way, so its value should not be included in any file -contents. - - 'DESTDIR' support is commonly used in package creation. It is also -helpful to users who want to understand what a given package will -install where, and to allow users who don't normally have permissions to -install into protected areas to build and install before gaining those -permissions. Finally, it can be useful with tools such as 'stow', where -code is installed in one place but made to appear to be installed -somewhere else using symbolic links or special mount operations. So, we -strongly recommend GNU packages support 'DESTDIR', though it is not an -absolute requirement. - - -File: standards.info, Node: Directory Variables, Next: Standard Targets, Prev: DESTDIR, Up: Makefile Conventions - -7.2.5 Variables for Installation Directories --------------------------------------------- - -Installation directories should always be named by variables, so it is -easy to install in a nonstandard place. The standard names for these -variables and the values they should have in GNU packages are described -below. They are based on a standard file system layout; variants of it -are used in GNU/Linux and other modern operating systems. - - Installers are expected to override these values when calling 'make' -(e.g., 'make prefix=/usr install' or 'configure' (e.g., 'configure ---prefix=/usr'). GNU packages should not try to guess which value -should be appropriate for these variables on the system they are being -installed onto: use the default settings specified here so that all GNU -packages behave identically, allowing the installer to achieve any -desired layout. - - These first two variables set the root for the installation. All the -other installation directories should be subdirectories of one of these -two, and nothing should be directly installed into these two -directories. - -'prefix' - A prefix used in constructing the default values of the variables - listed below. The default value of 'prefix' should be - '/usr/local'. When building the complete GNU system, the prefix - will be empty and '/usr' will be a symbolic link to '/'. (If you - are using Autoconf, write it as '@prefix@'.) - - Running 'make install' with a different value of 'prefix' from the - one used to build the program should _not_ recompile the program. - -'exec_prefix' - A prefix used in constructing the default values of some of the - variables listed below. The default value of 'exec_prefix' should - be '$(prefix)'. (If you are using Autoconf, write it as - '@exec_prefix@'.) - - Generally, '$(exec_prefix)' is used for directories that contain - machine-specific files (such as executables and subroutine - libraries), while '$(prefix)' is used directly for other - directories. - - Running 'make install' with a different value of 'exec_prefix' from - the one used to build the program should _not_ recompile the - program. - - Executable programs are installed in one of the following -directories. - -'bindir' - The directory for installing executable programs that users can - run. This should normally be '/usr/local/bin', but write it as - '$(exec_prefix)/bin'. (If you are using Autoconf, write it as - '@bindir@'.) - -'sbindir' - The directory for installing executable programs that can be run - from the shell, but are only generally useful to system - administrators. This should normally be '/usr/local/sbin', but - write it as '$(exec_prefix)/sbin'. (If you are using Autoconf, - write it as '@sbindir@'.) - -'libexecdir' - The directory for installing executable programs to be run by other - programs rather than by users. This directory should normally be - '/usr/local/libexec', but write it as '$(exec_prefix)/libexec'. - (If you are using Autoconf, write it as '@libexecdir@'.) - - The definition of 'libexecdir' is the same for all packages, so you - should install your data in a subdirectory thereof. Most packages - install their data under '$(libexecdir)/PACKAGE-NAME/', possibly - within additional subdirectories thereof, such as - '$(libexecdir)/PACKAGE-NAME/MACHINE/VERSION'. - - Data files used by the program during its execution are divided into -categories in two ways. - - * Some files are normally modified by programs; others are never - normally modified (though users may edit some of these). - - * Some files are architecture-independent and can be shared by all - machines at a site; some are architecture-dependent and can be - shared only by machines of the same kind and operating system; - others may never be shared between two machines. - - This makes for six different possibilities. However, we want to -discourage the use of architecture-dependent files, aside from object -files and libraries. It is much cleaner to make other data files -architecture-independent, and it is generally not hard. - - Here are the variables Makefiles should use to specify directories to -put these various kinds of files in: - -'datarootdir' - The root of the directory tree for read-only - architecture-independent data files. This should normally be - '/usr/local/share', but write it as '$(prefix)/share'. (If you are - using Autoconf, write it as '@datarootdir@'.) 'datadir''s default - value is based on this variable; so are 'infodir', 'mandir', and - others. - -'datadir' - The directory for installing idiosyncratic read-only - architecture-independent data files for this program. This is - usually the same place as 'datarootdir', but we use the two - separate variables so that you can move these program-specific - files without altering the location for Info files, man pages, etc. - - This should normally be '/usr/local/share', but write it as - '$(datarootdir)'. (If you are using Autoconf, write it as - '@datadir@'.) - - The definition of 'datadir' is the same for all packages, so you - should install your data in a subdirectory thereof. Most packages - install their data under '$(datadir)/PACKAGE-NAME/'. - -'sysconfdir' - The directory for installing read-only data files that pertain to a - single machine-that is to say, files for configuring a host. - Mailer and network configuration files, '/etc/passwd', and so forth - belong here. All the files in this directory should be ordinary - ASCII text files. This directory should normally be - '/usr/local/etc', but write it as '$(prefix)/etc'. (If you are - using Autoconf, write it as '@sysconfdir@'.) - - Do not install executables here in this directory (they probably - belong in '$(libexecdir)' or '$(sbindir)'). Also do not install - files that are modified in the normal course of their use (programs - whose purpose is to change the configuration of the system - excluded). Those probably belong in '$(localstatedir)'. - -'sharedstatedir' - The directory for installing architecture-independent data files - which the programs modify while they run. This should normally be - '/usr/local/com', but write it as '$(prefix)/com'. (If you are - using Autoconf, write it as '@sharedstatedir@'.) - -'localstatedir' - The directory for installing data files which the programs modify - while they run, and that pertain to one specific machine. Users - should never need to modify files in this directory to configure - the package's operation; put such configuration information in - separate files that go in '$(datadir)' or '$(sysconfdir)'. - '$(localstatedir)' should normally be '/usr/local/var', but write - it as '$(prefix)/var'. (If you are using Autoconf, write it as - '@localstatedir@'.) - - These variables specify the directory for installing certain specific -types of files, if your program has them. Every GNU package should have -Info files, so every program needs 'infodir', but not all need 'libdir' -or 'lispdir'. - -'includedir' - The directory for installing header files to be included by user - programs with the C '#include' preprocessor directive. This should - normally be '/usr/local/include', but write it as - '$(prefix)/include'. (If you are using Autoconf, write it as - '@includedir@'.) - - Most compilers other than GCC do not look for header files in - directory '/usr/local/include'. So installing the header files - this way is only useful with GCC. Sometimes this is not a problem - because some libraries are only really intended to work with GCC. - But some libraries are intended to work with other compilers. They - should install their header files in two places, one specified by - 'includedir' and one specified by 'oldincludedir'. - -'oldincludedir' - The directory for installing '#include' header files for use with - compilers other than GCC. This should normally be '/usr/include'. - (If you are using Autoconf, you can write it as '@oldincludedir@'.) - - The Makefile commands should check whether the value of - 'oldincludedir' is empty. If it is, they should not try to use it; - they should cancel the second installation of the header files. - - A package should not replace an existing header in this directory - unless the header came from the same package. Thus, if your Foo - package provides a header file 'foo.h', then it should install the - header file in the 'oldincludedir' directory if either (1) there is - no 'foo.h' there or (2) the 'foo.h' that exists came from the Foo - package. - - To tell whether 'foo.h' came from the Foo package, put a magic - string in the file--part of a comment--and 'grep' for that string. - -'docdir' - The directory for installing documentation files (other than Info) - for this package. By default, it should be - '/usr/local/share/doc/YOURPKG', but it should be written as - '$(datarootdir)/doc/YOURPKG'. (If you are using Autoconf, write it - as '@docdir@'.) The YOURPKG subdirectory, which may include a - version number, prevents collisions among files with common names, - such as 'README'. - -'infodir' - The directory for installing the Info files for this package. By - default, it should be '/usr/local/share/info', but it should be - written as '$(datarootdir)/info'. (If you are using Autoconf, - write it as '@infodir@'.) 'infodir' is separate from 'docdir' for - compatibility with existing practice. - -'htmldir' -'dvidir' -'pdfdir' -'psdir' - Directories for installing documentation files in the particular - format. They should all be set to '$(docdir)' by default. (If you - are using Autoconf, write them as '@htmldir@', '@dvidir@', etc.) - Packages which supply several translations of their documentation - should install them in '$(htmldir)/'LL, '$(pdfdir)/'LL, etc. where - LL is a locale abbreviation such as 'en' or 'pt_BR'. - -'libdir' - The directory for object files and libraries of object code. Do - not install executables here, they probably ought to go in - '$(libexecdir)' instead. The value of 'libdir' should normally be - '/usr/local/lib', but write it as '$(exec_prefix)/lib'. (If you - are using Autoconf, write it as '@libdir@'.) - -'lispdir' - The directory for installing any Emacs Lisp files in this package. - By default, it should be '/usr/local/share/emacs/site-lisp', but it - should be written as '$(datarootdir)/emacs/site-lisp'. - - If you are using Autoconf, write the default as '@lispdir@'. In - order to make '@lispdir@' work, you need the following lines in - your 'configure.in' file: - - lispdir='${datarootdir}/emacs/site-lisp' - AC_SUBST(lispdir) - -'localedir' - The directory for installing locale-specific message catalogs for - this package. By default, it should be '/usr/local/share/locale', - but it should be written as '$(datarootdir)/locale'. (If you are - using Autoconf, write it as '@localedir@'.) This directory usually - has a subdirectory per locale. - - Unix-style man pages are installed in one of the following: - -'mandir' - The top-level directory for installing the man pages (if any) for - this package. It will normally be '/usr/local/share/man', but you - should write it as '$(datarootdir)/man'. (If you are using - Autoconf, write it as '@mandir@'.) - -'man1dir' - The directory for installing section 1 man pages. Write it as - '$(mandir)/man1'. -'man2dir' - The directory for installing section 2 man pages. Write it as - '$(mandir)/man2' -'...' - - *Don't make the primary documentation for any GNU software be a man - page. Write a manual in Texinfo instead. Man pages are just for - the sake of people running GNU software on Unix, which is a - secondary application only.* - -'manext' - The file name extension for the installed man page. This should - contain a period followed by the appropriate digit; it should - normally be '.1'. - -'man1ext' - The file name extension for installed section 1 man pages. -'man2ext' - The file name extension for installed section 2 man pages. -'...' - Use these names instead of 'manext' if the package needs to install - man pages in more than one section of the manual. - - And finally, you should set the following variable: - -'srcdir' - The directory for the sources being compiled. The value of this - variable is normally inserted by the 'configure' shell script. (If - you are using Autoconf, use 'srcdir = @srcdir@'.) - - For example: - - # Common prefix for installation directories. - # NOTE: This directory must exist when you start the install. - prefix = /usr/local - datarootdir = $(prefix)/share - datadir = $(datarootdir) - exec_prefix = $(prefix) - # Where to put the executable for the command `gcc'. - bindir = $(exec_prefix)/bin - # Where to put the directories used by the compiler. - libexecdir = $(exec_prefix)/libexec - # Where to put the Info files. - infodir = $(datarootdir)/info - - If your program installs a large number of files into one of the -standard user-specified directories, it might be useful to group them -into a subdirectory particular to that program. If you do this, you -should write the 'install' rule to create these subdirectories. - - Do not expect the user to include the subdirectory name in the value -of any of the variables listed above. The idea of having a uniform set -of variable names for installation directories is to enable the user to -specify the exact same values for several different GNU packages. In -order for this to be useful, all the packages must be designed so that -they will work sensibly when the user does so. - - At times, not all of these variables may be implemented in the -current release of Autoconf and/or Automake; but as of Autoconf 2.60, we -believe all of them are. When any are missing, the descriptions here -serve as specifications for what Autoconf will implement. As a -programmer, you can either use a development version of Autoconf or -avoid using these variables until a stable release is made which -supports them. - - -File: standards.info, Node: Standard Targets, Next: Install Command Categories, Prev: Directory Variables, Up: Makefile Conventions - -7.2.6 Standard Targets for Users --------------------------------- - -All GNU programs should have the following targets in their Makefiles: - -'all' - Compile the entire program. This should be the default target. - This target need not rebuild any documentation files; Info files - should normally be included in the distribution, and DVI (and other - documentation format) files should be made only when explicitly - asked for. - - By default, the Make rules should compile and link with '-g', so - that executable programs have debugging symbols. Users who don't - mind being helpless can strip the executables later if they wish. - -'install' - Compile the program and copy the executables, libraries, and so on - to the file names where they should reside for actual use. If - there is a simple test to verify that a program is properly - installed, this target should run that test. - - Do not strip executables when installing them. Devil-may-care - users can use the 'install-strip' target to do that. - - If possible, write the 'install' target rule so that it does not - modify anything in the directory where the program was built, - provided 'make all' has just been done. This is convenient for - building the program under one user name and installing it under - another. - - The commands should create all the directories in which files are - to be installed, if they don't already exist. This includes the - directories specified as the values of the variables 'prefix' and - 'exec_prefix', as well as all subdirectories that are needed. One - way to do this is by means of an 'installdirs' target as described - below. - - Use '-' before any command for installing a man page, so that - 'make' will ignore any errors. This is in case there are systems - that don't have the Unix man page documentation system installed. - - The way to install Info files is to copy them into '$(infodir)' - with '$(INSTALL_DATA)' (*note Command Variables::), and then run - the 'install-info' program if it is present. 'install-info' is a - program that edits the Info 'dir' file to add or update the menu - entry for the given Info file; it is part of the Texinfo package. - Here is a sample rule to install an Info file: - - $(DESTDIR)$(infodir)/foo.info: foo.info - $(POST_INSTALL) - # There may be a newer info file in . than in srcdir. - -if test -f foo.info; then d=.; \ - else d=$(srcdir); fi; \ - $(INSTALL_DATA) $$d/foo.info $(DESTDIR)$@; \ - # Run install-info only if it exists. - # Use `if' instead of just prepending `-' to the - # line so we notice real errors from install-info. - # We use `$(SHELL) -c' because some shells do not - # fail gracefully when there is an unknown command. - if $(SHELL) -c 'install-info --version' \ - >/dev/null 2>&1; then \ - install-info --dir-file=$(DESTDIR)$(infodir)/dir \ - $(DESTDIR)$(infodir)/foo.info; \ - else true; fi - - When writing the 'install' target, you must classify all the - commands into three categories: normal ones, "pre-installation" - commands and "post-installation" commands. *Note Install Command - Categories::. - -'install-html' -'install-dvi' -'install-pdf' -'install-ps' - These targets install documentation in formats other than Info; - they're intended to be called explicitly by the person installing - the package, if that format is desired. GNU prefers Info files, so - these must be installed by the 'install' target. - - When you have many documentation files to install, we recommend - that you avoid collisions and clutter by arranging for these - targets to install in subdirectories of the appropriate - installation directory, such as 'htmldir'. As one example, if your - package has multiple manuals, and you wish to install HTML - documentation with many files (such as the "split" mode output by - 'makeinfo --html'), you'll certainly want to use subdirectories, or - two nodes with the same name in different manuals will overwrite - each other. - - Please make these 'install-FORMAT' targets invoke the commands for - the FORMAT target, for example, by making FORMAT a dependency. - -'uninstall' - Delete all the installed files--the copies that the 'install' and - 'install-*' targets create. - - This rule should not modify the directories where compilation is - done, only the directories where files are installed. - - The uninstallation commands are divided into three categories, just - like the installation commands. *Note Install Command - Categories::. - -'install-strip' - Like 'install', but strip the executable files while installing - them. In simple cases, this target can use the 'install' target in - a simple way: - - install-strip: - $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \ - install - - But if the package installs scripts as well as real executables, - the 'install-strip' target can't just refer to the 'install' - target; it has to strip the executables but not the scripts. - - 'install-strip' should not strip the executables in the build - directory which are being copied for installation. It should only - strip the copies that are installed. - - Normally we do not recommend stripping an executable unless you are - sure the program has no bugs. However, it can be reasonable to - install a stripped executable for actual execution while saving the - unstripped executable elsewhere in case there is a bug. - -'clean' - - Delete all files in the current directory that are normally created - by building the program. Also delete files in other directories if - they are created by this makefile. However, don't delete the files - that record the configuration. Also preserve files that could be - made by building, but normally aren't because the distribution - comes with them. There is no need to delete parent directories - that were created with 'mkdir -p', since they could have existed - anyway. - - Delete '.dvi' files here if they are not part of the distribution. - -'distclean' - Delete all files in the current directory (or created by this - makefile) that are created by configuring or building the program. - If you have unpacked the source and built the program without - creating any other files, 'make distclean' should leave only the - files that were in the distribution. However, there is no need to - delete parent directories that were created with 'mkdir -p', since - they could have existed anyway. - -'mostlyclean' - Like 'clean', but may refrain from deleting a few files that people - normally don't want to recompile. For example, the 'mostlyclean' - target for GCC does not delete 'libgcc.a', because recompiling it - is rarely necessary and takes a lot of time. - -'maintainer-clean' - Delete almost everything that can be reconstructed with this - Makefile. This typically includes everything deleted by - 'distclean', plus more: C source files produced by Bison, tags - tables, Info files, and so on. - - The reason we say "almost everything" is that running the command - 'make maintainer-clean' should not delete 'configure' even if - 'configure' can be remade using a rule in the Makefile. More - generally, 'make maintainer-clean' should not delete anything that - needs to exist in order to run 'configure' and then begin to build - the program. Also, there is no need to delete parent directories - that were created with 'mkdir -p', since they could have existed - anyway. These are the only exceptions; 'maintainer-clean' should - delete everything else that can be rebuilt. - - The 'maintainer-clean' target is intended to be used by a - maintainer of the package, not by ordinary users. You may need - special tools to reconstruct some of the files that 'make - maintainer-clean' deletes. Since these files are normally included - in the distribution, we don't take care to make them easy to - reconstruct. If you find you need to unpack the full distribution - again, don't blame us. - - To help make users aware of this, the commands for the special - 'maintainer-clean' target should start with these two: - - @echo 'This command is intended for maintainers to use; it' - @echo 'deletes files that may need special tools to rebuild.' - -'TAGS' - Update a tags table for this program. - -'info' - Generate any Info files needed. The best way to write the rules is - as follows: - - info: foo.info - - foo.info: foo.texi chap1.texi chap2.texi - $(MAKEINFO) $(srcdir)/foo.texi - - You must define the variable 'MAKEINFO' in the Makefile. It should - run the 'makeinfo' program, which is part of the Texinfo - distribution. - - Normally a GNU distribution comes with Info files, and that means - the Info files are present in the source directory. Therefore, the - Make rule for an info file should update it in the source - directory. When users build the package, ordinarily Make will not - update the Info files because they will already be up to date. - -'dvi' -'html' -'pdf' -'ps' - Generate documentation files in the given format. These targets - should always exist, but any or all can be a no-op if the given - output format cannot be generated. These targets should not be - dependencies of the 'all' target; the user must manually invoke - them. - - Here's an example rule for generating DVI files from Texinfo: - - dvi: foo.dvi - - foo.dvi: foo.texi chap1.texi chap2.texi - $(TEXI2DVI) $(srcdir)/foo.texi - - You must define the variable 'TEXI2DVI' in the Makefile. It should - run the program 'texi2dvi', which is part of the Texinfo - distribution.(1) Alternatively, write just the dependencies, and - allow GNU 'make' to provide the command. - - Here's another example, this one for generating HTML from Texinfo: - - html: foo.html - - foo.html: foo.texi chap1.texi chap2.texi - $(TEXI2HTML) $(srcdir)/foo.texi - - Again, you would define the variable 'TEXI2HTML' in the Makefile; - for example, it might run 'makeinfo --no-split --html' ('makeinfo' - is part of the Texinfo distribution). - -'dist' - Create a distribution tar file for this program. The tar file - should be set up so that the file names in the tar file start with - a subdirectory name which is the name of the package it is a - distribution for. This name can include the version number. - - For example, the distribution tar file of GCC version 1.40 unpacks - into a subdirectory named 'gcc-1.40'. - - The easiest way to do this is to create a subdirectory - appropriately named, use 'ln' or 'cp' to install the proper files - in it, and then 'tar' that subdirectory. - - Compress the tar file with 'gzip'. For example, the actual - distribution file for GCC version 1.40 is called 'gcc-1.40.tar.gz'. - - The 'dist' target should explicitly depend on all non-source files - that are in the distribution, to make sure they are up to date in - the distribution. *Note Making Releases: Releases. - -'check' - Perform self-tests (if any). The user must build the program - before running the tests, but need not install the program; you - should write the self-tests so that they work when the program is - built but not installed. - - The following targets are suggested as conventional names, for -programs in which they are useful. - -'installcheck' - Perform installation tests (if any). The user must build and - install the program before running the tests. You should not - assume that '$(bindir)' is in the search path. - -'installdirs' - It's useful to add a target named 'installdirs' to create the - directories where files are installed, and their parent - directories. There is a script called 'mkinstalldirs' which is - convenient for this; you can find it in the Texinfo package. You - can use a rule like this: - - # Make sure all installation directories (e.g. $(bindir)) - # actually exist by making them if necessary. - installdirs: mkinstalldirs - $(srcdir)/mkinstalldirs $(bindir) $(datadir) \ - $(libdir) $(infodir) \ - $(mandir) - - or, if you wish to support 'DESTDIR', - - # Make sure all installation directories (e.g. $(bindir)) - # actually exist by making them if necessary. - installdirs: mkinstalldirs - $(srcdir)/mkinstalldirs \ - $(DESTDIR)$(bindir) $(DESTDIR)$(datadir) \ - $(DESTDIR)$(libdir) $(DESTDIR)$(infodir) \ - $(DESTDIR)$(mandir) - - This rule should not modify the directories where compilation is - done. It should do nothing but create installation directories. - - ---------- Footnotes ---------- - - (1) 'texi2dvi' uses TeX to do the real work of formatting. TeX is -not distributed with Texinfo. - - -File: standards.info, Node: Install Command Categories, Prev: Standard Targets, Up: Makefile Conventions - -7.2.7 Install Command Categories --------------------------------- - -When writing the 'install' target, you must classify all the commands -into three categories: normal ones, "pre-installation" commands and -"post-installation" commands. - - Normal commands move files into their proper places, and set their -modes. They may not alter any files except the ones that come entirely -from the package they belong to. - - Pre-installation and post-installation commands may alter other -files; in particular, they can edit global configuration files or data -bases. - - Pre-installation commands are typically executed before the normal -commands, and post-installation commands are typically run after the -normal commands. - - The most common use for a post-installation command is to run -'install-info'. This cannot be done with a normal command, since it -alters a file (the Info directory) which does not come entirely and -solely from the package being installed. It is a post-installation -command because it needs to be done after the normal command which -installs the package's Info files. - - Most programs don't need any pre-installation commands, but we have -the feature just in case it is needed. - - To classify the commands in the 'install' rule into these three -categories, insert "category lines" among them. A category line -specifies the category for the commands that follow. - - A category line consists of a tab and a reference to a special Make -variable, plus an optional comment at the end. There are three -variables you can use, one for each category; the variable name -specifies the category. Category lines are no-ops in ordinary execution -because these three Make variables are normally undefined (and you -_should not_ define them in the makefile). - - Here are the three possible category lines, each with a comment that -explains what it means: - - $(PRE_INSTALL) # Pre-install commands follow. - $(POST_INSTALL) # Post-install commands follow. - $(NORMAL_INSTALL) # Normal commands follow. - - If you don't use a category line at the beginning of the 'install' -rule, all the commands are classified as normal until the first category -line. If you don't use any category lines, all the commands are -classified as normal. - - These are the category lines for 'uninstall': - - $(PRE_UNINSTALL) # Pre-uninstall commands follow. - $(POST_UNINSTALL) # Post-uninstall commands follow. - $(NORMAL_UNINSTALL) # Normal commands follow. - - Typically, a pre-uninstall command would be used for deleting entries -from the Info directory. - - If the 'install' or 'uninstall' target has any dependencies which act -as subroutines of installation, then you should start _each_ -dependency's commands with a category line, and start the main target's -commands with a category line also. This way, you can ensure that each -command is placed in the right category regardless of which of the -dependencies actually run. - - Pre-installation and post-installation commands should not run any -programs except for these: - - [ basename bash cat chgrp chmod chown cmp cp dd diff echo - egrep expand expr false fgrep find getopt grep gunzip gzip - hostname install install-info kill ldconfig ln ls md5sum - mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee - test touch true uname xargs yes - - The reason for distinguishing the commands in this way is for the -sake of making binary packages. Typically a binary package contains all -the executables and other files that need to be installed, and has its -own method of installing them--so it does not need to run the normal -installation commands. But installing the binary package does need to -execute the pre-installation and post-installation commands. - - Programs to build binary packages work by extracting the -pre-installation and post-installation commands. Here is one way of -extracting the pre-installation commands (the '-s' option to 'make' is -needed to silence messages about entering subdirectories): - - make -s -n install -o all \ - PRE_INSTALL=pre-install \ - POST_INSTALL=post-install \ - NORMAL_INSTALL=normal-install \ - | gawk -f pre-install.awk - -where the file 'pre-install.awk' could contain this: - - $0 ~ /^(normal-install|post-install)[ \t]*$/ {on = 0} - on {print $0} - $0 ~ /^pre-install[ \t]*$/ {on = 1} - - -File: standards.info, Node: Releases, Prev: Makefile Conventions, Up: Managing Releases - -7.3 Making Releases -=================== - -You should identify each release with a pair of version numbers, a major -version and a minor. We have no objection to using more than two -numbers, but it is very unlikely that you really need them. - - Package the distribution of 'Foo version 69.96' up in a gzipped tar -file with the name 'foo-69.96.tar.gz'. It should unpack into a -subdirectory named 'foo-69.96'. - - Building and installing the program should never modify any of the -files contained in the distribution. This means that all the files that -form part of the program in any way must be classified into "source -files" and "non-source files". Source files are written by humans and -never changed automatically; non-source files are produced from source -files by programs under the control of the Makefile. - - The distribution should contain a file named 'README' which gives the -name of the package, and a general description of what it does. It is -also good to explain the purpose of each of the first-level -subdirectories in the package, if there are any. The 'README' file -should either state the version number of the package, or refer to where -in the package it can be found. - - The 'README' file should refer to the file 'INSTALL', which should -contain an explanation of the installation procedure. - - The 'README' file should also refer to the file which contains the -copying conditions. The GNU GPL, if used, should be in a file called -'COPYING'. If the GNU LGPL is used, it should be in a file called -'COPYING.LESSER'. - - Naturally, all the source files must be in the distribution. It is -okay to include non-source files in the distribution, provided they are -up-to-date and machine-independent, so that building the distribution -normally will never modify them. We commonly include non-source files -produced by Bison, 'lex', TeX, and 'makeinfo'; this helps avoid -unnecessary dependencies between our distributions, so that users can -install whichever packages they want to install. - - Non-source files that might actually be modified by building and -installing the program should *never* be included in the distribution. -So if you do distribute non-source files, always make sure they are up -to date when you make a new distribution. - - Make sure that all the files in the distribution are world-readable, -and that directories are world-readable and world-searchable (octal mode -755). We used to recommend that all directories in the distribution -also be world-writable (octal mode 777), because ancient versions of -'tar' would otherwise not cope when extracting the archive as an -unprivileged user. That can easily lead to security issues when -creating the archive, however, so now we recommend against that. - - Don't include any symbolic links in the distribution itself. If the -tar file contains symbolic links, then people cannot even unpack it on -systems that don't support symbolic links. Also, don't use multiple -names for one file in different directories, because certain file -systems cannot handle this and that prevents unpacking the distribution. - - Try to make sure that all the file names will be unique on MS-DOS. A -name on MS-DOS consists of up to 8 characters, optionally followed by a -period and up to three characters. MS-DOS will truncate extra -characters both before and after the period. Thus, 'foobarhacker.c' and -'foobarhacker.o' are not ambiguous; they are truncated to 'foobarha.c' -and 'foobarha.o', which are distinct. - - Include in your distribution a copy of the 'texinfo.tex' you used to -test print any '*.texinfo' or '*.texi' files. - - Likewise, if your program uses small GNU software packages like -regex, getopt, obstack, or termcap, include them in the distribution -file. Leaving them out would make the distribution file a little -smaller at the expense of possible inconvenience to a user who doesn't -know what other files to get. - - -File: standards.info, Node: References, Next: GNU Free Documentation License, Prev: Managing Releases, Up: Top - -8 References to Non-Free Software and Documentation -*************************************************** - -A GNU program should not recommend, promote, or grant legitimacy to the -use of any non-free program. Proprietary software is a social and -ethical problem, and our aim is to put an end to that problem. We can't -stop some people from writing proprietary programs, or stop other people -from using them, but we can and should refuse to advertise them to new -potential customers, or to give the public the idea that their existence -is ethical. - - The GNU definition of free software is found on the GNU web site at -, and the definition of free -documentation is found at . -The terms "free" and "non-free", used in this document, refer to those -definitions. - - A list of important licenses and whether they qualify as free is in -. If it is not clear -whether a license qualifies as free, please ask the GNU Project by -writing to . We will answer, and if the license is -an important one, we will add it to the list. - - When a non-free program or system is well known, you can mention it -in passing--that is harmless, since users who might want to use it -probably already know about it. For instance, it is fine to explain how -to build your package on top of some widely used non-free operating -system, or how to use it together with some widely used non-free -program. - - However, you should give only the necessary information to help those -who already use the non-free program to use your program with it--don't -give, or refer to, any further information about the proprietary -program, and don't imply that the proprietary program enhances your -program, or that its existence is in any way a good thing. The goal -should be that people already using the proprietary program will get the -advice they need about how to use your free program with it, while -people who don't already use the proprietary program will not see -anything likely to lead them to take an interest in it. - - If a non-free program or system is obscure in your program's domain, -your program should not mention or support it at all, since doing so -would tend to popularize the non-free program more than it popularizes -your program. (You cannot hope to find many additional users for your -program among the users of Foobar, if the existence of Foobar is not -generally known among people who might want to use your program.) - - Sometimes a program is free software in itself but depends on a -non-free platform in order to run. For instance, many Java programs -depend on some non-free Java libraries. To recommend or promote such a -program is to promote the other programs it needs. This is why we are -careful about listing Java programs in the Free Software Directory: we -don't want to promote the non-free Java libraries. - - We hope this particular problem with Java will be gone by and by, as -we replace the remaining non-free standard Java libraries with free -software, but the general principle will remain the same: don't -recommend, promote or legitimize programs that depend on non-free -software to run. - - Some free programs strongly encourage the use of non-free software. -A typical example is 'mplayer'. It is free software in itself, and the -free code can handle some kinds of files. However, 'mplayer' recommends -use of non-free codecs for other kinds of files, and users that install -'mplayer' are very likely to install those codecs along with it. To -recommend 'mplayer' is, in effect, to promote use of the non-free -codecs. - - Thus, you should not recommend programs that strongly encourage the -use of non-free software. This is why we do not list 'mplayer' in the -Free Software Directory. - - A GNU package should not refer the user to any non-free documentation -for free software. Free documentation that can be included in free -operating systems is essential for completing the GNU system, or any -free operating system, so encouraging it is a priority; to recommend use -of documentation that we are not allowed to include undermines the -impetus for the community to produce documentation that we can include. -So GNU packages should never recommend non-free documentation. - - By contrast, it is ok to refer to journal articles and textbooks in -the comments of a program for explanation of how it functions, even -though they are non-free. This is because we don't include such things -in the GNU system even they are free--they are outside the scope of what -a software distribution needs to include. - - Referring to a web site that describes or recommends a non-free -program is promoting that program, so please do not make links (or -mention by name) web sites that contain such material. This policy is -relevant particularly for the web pages for a GNU package. - - Following links from nearly any web site can lead eventually to -non-free software; this is inherent in the nature of the web. So it -makes no sense to criticize a site for having such links. As long as -the site does not itself recommend a non-free program, there is no need -to consider the question of the sites that it links to for other -reasons. - - Thus, for example, you should not refer to AT&T's web site if that -recommends AT&T's non-free software packages; you should not refer to a -site that links to AT&T's site presenting it as a place to get some -non-free program, because that link recommends and legitimizes the -non-free program. However, that a site contains a link to AT&T's web -site for some other purpose (such as long-distance telephone service) is -not an objection against it. - - -File: standards.info, Node: GNU Free Documentation License, Next: Index, Prev: References, Up: Top - -Appendix A GNU Free Documentation License -***************************************** - - Version 1.3, 3 November 2008 - - Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. - - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - 0. PREAMBLE - - The purpose of this License is to make a manual, textbook, or other - functional and useful document "free" in the sense of freedom: to - assure everyone the effective freedom to copy and redistribute it, - with or without modifying it, either commercially or - noncommercially. Secondarily, this License preserves for the - author and publisher a way to get credit for their work, while not - being considered responsible for modifications made by others. - - This License is a kind of "copyleft", which means that derivative - works of the document must themselves be free in the same sense. - It complements the GNU General Public License, which is a copyleft - license designed for free software. - - We have designed this License in order to use it for manuals for - free software, because free software needs free documentation: a - free program should come with manuals providing the same freedoms - that the software does. But this License is not limited to - software manuals; it can be used for any textual work, regardless - of subject matter or whether it is published as a printed book. We - recommend this License principally for works whose purpose is - instruction or reference. - - 1. APPLICABILITY AND DEFINITIONS - - This License applies to any manual or other work, in any medium, - that contains a notice placed by the copyright holder saying it can - be distributed under the terms of this License. Such a notice - grants a world-wide, royalty-free license, unlimited in duration, - to use that work under the conditions stated herein. The - "Document", below, refers to any such manual or work. Any member - of the public is a licensee, and is addressed as "you". You accept - the license if you copy, modify or distribute the work in a way - requiring permission under copyright law. - - A "Modified Version" of the Document means any work containing the - Document or a portion of it, either copied verbatim, or with - modifications and/or translated into another language. - - A "Secondary Section" is a named appendix or a front-matter section - of the Document that deals exclusively with the relationship of the - publishers or authors of the Document to the Document's overall - subject (or to related matters) and contains nothing that could - fall directly within that overall subject. (Thus, if the Document - is in part a textbook of mathematics, a Secondary Section may not - explain any mathematics.) The relationship could be a matter of - historical connection with the subject or with related matters, or - of legal, commercial, philosophical, ethical or political position - regarding them. - - The "Invariant Sections" are certain Secondary Sections whose - titles are designated, as being those of Invariant Sections, in the - notice that says that the Document is released under this License. - If a section does not fit the above definition of Secondary then it - is not allowed to be designated as Invariant. The Document may - contain zero Invariant Sections. If the Document does not identify - any Invariant Sections then there are none. - - The "Cover Texts" are certain short passages of text that are - listed, as Front-Cover Texts or Back-Cover Texts, in the notice - that says that the Document is released under this License. A - Front-Cover Text may be at most 5 words, and a Back-Cover Text may - be at most 25 words. - - A "Transparent" copy of the Document means a machine-readable copy, - represented in a format whose specification is available to the - general public, that is suitable for revising the document - straightforwardly with generic text editors or (for images composed - of pixels) generic paint programs or (for drawings) some widely - available drawing editor, and that is suitable for input to text - formatters or for automatic translation to a variety of formats - suitable for input to text formatters. A copy made in an otherwise - Transparent file format whose markup, or absence of markup, has - been arranged to thwart or discourage subsequent modification by - readers is not Transparent. An image format is not Transparent if - used for any substantial amount of text. A copy that is not - "Transparent" is called "Opaque". - - Examples of suitable formats for Transparent copies include plain - ASCII without markup, Texinfo input format, LaTeX input format, - SGML or XML using a publicly available DTD, and standard-conforming - simple HTML, PostScript or PDF designed for human modification. - Examples of transparent image formats include PNG, XCF and JPG. - Opaque formats include proprietary formats that can be read and - edited only by proprietary word processors, SGML or XML for which - the DTD and/or processing tools are not generally available, and - the machine-generated HTML, PostScript or PDF produced by some word - processors for output purposes only. - - The "Title Page" means, for a printed book, the title page itself, - plus such following pages as are needed to hold, legibly, the - material this License requires to appear in the title page. For - works in formats which do not have any title page as such, "Title - Page" means the text near the most prominent appearance of the - work's title, preceding the beginning of the body of the text. - - The "publisher" means any person or entity that distributes copies - of the Document to the public. - - A section "Entitled XYZ" means a named subunit of the Document - whose title either is precisely XYZ or contains XYZ in parentheses - following text that translates XYZ in another language. (Here XYZ - stands for a specific section name mentioned below, such as - "Acknowledgements", "Dedications", "Endorsements", or "History".) - To "Preserve the Title" of such a section when you modify the - Document means that it remains a section "Entitled XYZ" according - to this definition. - - The Document may include Warranty Disclaimers next to the notice - which states that this License applies to the Document. These - Warranty Disclaimers are considered to be included by reference in - this License, but only as regards disclaiming warranties: any other - implication that these Warranty Disclaimers may have is void and - has no effect on the meaning of this License. - - 2. VERBATIM COPYING - - You may copy and distribute the Document in any medium, either - commercially or noncommercially, provided that this License, the - copyright notices, and the license notice saying this License - applies to the Document are reproduced in all copies, and that you - add no other conditions whatsoever to those of this License. You - may not use technical measures to obstruct or control the reading - or further copying of the copies you make or distribute. However, - you may accept compensation in exchange for copies. If you - distribute a large enough number of copies you must also follow the - conditions in section 3. - - You may also lend copies, under the same conditions stated above, - and you may publicly display copies. - - 3. COPYING IN QUANTITY - - If you publish printed copies (or copies in media that commonly - have printed covers) of the Document, numbering more than 100, and - the Document's license notice requires Cover Texts, you must - enclose the copies in covers that carry, clearly and legibly, all - these Cover Texts: Front-Cover Texts on the front cover, and - Back-Cover Texts on the back cover. Both covers must also clearly - and legibly identify you as the publisher of these copies. The - front cover must present the full title with all words of the title - equally prominent and visible. You may add other material on the - covers in addition. Copying with changes limited to the covers, as - long as they preserve the title of the Document and satisfy these - conditions, can be treated as verbatim copying in other respects. - - If the required texts for either cover are too voluminous to fit - legibly, you should put the first ones listed (as many as fit - reasonably) on the actual cover, and continue the rest onto - adjacent pages. - - If you publish or distribute Opaque copies of the Document - numbering more than 100, you must either include a machine-readable - Transparent copy along with each Opaque copy, or state in or with - each Opaque copy a computer-network location from which the general - network-using public has access to download using public-standard - network protocols a complete Transparent copy of the Document, free - of added material. If you use the latter option, you must take - reasonably prudent steps, when you begin distribution of Opaque - copies in quantity, to ensure that this Transparent copy will - remain thus accessible at the stated location until at least one - year after the last time you distribute an Opaque copy (directly or - through your agents or retailers) of that edition to the public. - - It is requested, but not required, that you contact the authors of - the Document well before redistributing any large number of copies, - to give them a chance to provide you with an updated version of the - Document. - - 4. MODIFICATIONS - - You may copy and distribute a Modified Version of the Document - under the conditions of sections 2 and 3 above, provided that you - release the Modified Version under precisely this License, with the - Modified Version filling the role of the Document, thus licensing - distribution and modification of the Modified Version to whoever - possesses a copy of it. In addition, you must do these things in - the Modified Version: - - A. Use in the Title Page (and on the covers, if any) a title - distinct from that of the Document, and from those of previous - versions (which should, if there were any, be listed in the - History section of the Document). You may use the same title - as a previous version if the original publisher of that - version gives permission. - - B. List on the Title Page, as authors, one or more persons or - entities responsible for authorship of the modifications in - the Modified Version, together with at least five of the - principal authors of the Document (all of its principal - authors, if it has fewer than five), unless they release you - from this requirement. - - C. State on the Title page the name of the publisher of the - Modified Version, as the publisher. - - D. Preserve all the copyright notices of the Document. - - E. Add an appropriate copyright notice for your modifications - adjacent to the other copyright notices. - - F. Include, immediately after the copyright notices, a license - notice giving the public permission to use the Modified - Version under the terms of this License, in the form shown in - the Addendum below. - - G. Preserve in that license notice the full lists of Invariant - Sections and required Cover Texts given in the Document's - license notice. - - H. Include an unaltered copy of this License. - - I. Preserve the section Entitled "History", Preserve its Title, - and add to it an item stating at least the title, year, new - authors, and publisher of the Modified Version as given on the - Title Page. If there is no section Entitled "History" in the - Document, create one stating the title, year, authors, and - publisher of the Document as given on its Title Page, then add - an item describing the Modified Version as stated in the - previous sentence. - - J. Preserve the network location, if any, given in the Document - for public access to a Transparent copy of the Document, and - likewise the network locations given in the Document for - previous versions it was based on. These may be placed in the - "History" section. You may omit a network location for a work - that was published at least four years before the Document - itself, or if the original publisher of the version it refers - to gives permission. - - K. For any section Entitled "Acknowledgements" or "Dedications", - Preserve the Title of the section, and preserve in the section - all the substance and tone of each of the contributor - acknowledgements and/or dedications given therein. - - L. Preserve all the Invariant Sections of the Document, unaltered - in their text and in their titles. Section numbers or the - equivalent are not considered part of the section titles. - - M. Delete any section Entitled "Endorsements". Such a section - may not be included in the Modified Version. - - N. Do not retitle any existing section to be Entitled - "Endorsements" or to conflict in title with any Invariant - Section. - - O. Preserve any Warranty Disclaimers. - - If the Modified Version includes new front-matter sections or - appendices that qualify as Secondary Sections and contain no - material copied from the Document, you may at your option designate - some or all of these sections as invariant. To do this, add their - titles to the list of Invariant Sections in the Modified Version's - license notice. These titles must be distinct from any other - section titles. - - You may add a section Entitled "Endorsements", provided it contains - nothing but endorsements of your Modified Version by various - parties--for example, statements of peer review or that the text - has been approved by an organization as the authoritative - definition of a standard. - - You may add a passage of up to five words as a Front-Cover Text, - and a passage of up to 25 words as a Back-Cover Text, to the end of - the list of Cover Texts in the Modified Version. Only one passage - of Front-Cover Text and one of Back-Cover Text may be added by (or - through arrangements made by) any one entity. If the Document - already includes a cover text for the same cover, previously added - by you or by arrangement made by the same entity you are acting on - behalf of, you may not add another; but you may replace the old - one, on explicit permission from the previous publisher that added - the old one. - - The author(s) and publisher(s) of the Document do not by this - License give permission to use their names for publicity for or to - assert or imply endorsement of any Modified Version. - - 5. COMBINING DOCUMENTS - - You may combine the Document with other documents released under - this License, under the terms defined in section 4 above for - modified versions, provided that you include in the combination all - of the Invariant Sections of all of the original documents, - unmodified, and list them all as Invariant Sections of your - combined work in its license notice, and that you preserve all - their Warranty Disclaimers. - - The combined work need only contain one copy of this License, and - multiple identical Invariant Sections may be replaced with a single - copy. If there are multiple Invariant Sections with the same name - but different contents, make the title of each such section unique - by adding at the end of it, in parentheses, the name of the - original author or publisher of that section if known, or else a - unique number. Make the same adjustment to the section titles in - the list of Invariant Sections in the license notice of the - combined work. - - In the combination, you must combine any sections Entitled - "History" in the various original documents, forming one section - Entitled "History"; likewise combine any sections Entitled - "Acknowledgements", and any sections Entitled "Dedications". You - must delete all sections Entitled "Endorsements." - - 6. COLLECTIONS OF DOCUMENTS - - You may make a collection consisting of the Document and other - documents released under this License, and replace the individual - copies of this License in the various documents with a single copy - that is included in the collection, provided that you follow the - rules of this License for verbatim copying of each of the documents - in all other respects. - - You may extract a single document from such a collection, and - distribute it individually under this License, provided you insert - a copy of this License into the extracted document, and follow this - License in all other respects regarding verbatim copying of that - document. - - 7. AGGREGATION WITH INDEPENDENT WORKS - - A compilation of the Document or its derivatives with other - separate and independent documents or works, in or on a volume of a - storage or distribution medium, is called an "aggregate" if the - copyright resulting from the compilation is not used to limit the - legal rights of the compilation's users beyond what the individual - works permit. When the Document is included in an aggregate, this - License does not apply to the other works in the aggregate which - are not themselves derivative works of the Document. - - If the Cover Text requirement of section 3 is applicable to these - copies of the Document, then if the Document is less than one half - of the entire aggregate, the Document's Cover Texts may be placed - on covers that bracket the Document within the aggregate, or the - electronic equivalent of covers if the Document is in electronic - form. Otherwise they must appear on printed covers that bracket - the whole aggregate. - - 8. TRANSLATION - - Translation is considered a kind of modification, so you may - distribute translations of the Document under the terms of section - 4. Replacing Invariant Sections with translations requires special - permission from their copyright holders, but you may include - translations of some or all Invariant Sections in addition to the - original versions of these Invariant Sections. You may include a - translation of this License, and all the license notices in the - Document, and any Warranty Disclaimers, provided that you also - include the original English version of this License and the - original versions of those notices and disclaimers. In case of a - disagreement between the translation and the original version of - this License or a notice or disclaimer, the original version will - prevail. - - If a section in the Document is Entitled "Acknowledgements", - "Dedications", or "History", the requirement (section 4) to - Preserve its Title (section 1) will typically require changing the - actual title. - - 9. TERMINATION - - You may not copy, modify, sublicense, or distribute the Document - except as expressly provided under this License. Any attempt - otherwise to copy, modify, sublicense, or distribute it is void, - and will automatically terminate your rights under this License. - - However, if you cease all violation of this License, then your - license from a particular copyright holder is reinstated (a) - provisionally, unless and until the copyright holder explicitly and - finally terminates your license, and (b) permanently, if the - copyright holder fails to notify you of the violation by some - reasonable means prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is - reinstated permanently if the copyright holder notifies you of the - violation by some reasonable means, this is the first time you have - received notice of violation of this License (for any work) from - that copyright holder, and you cure the violation prior to 30 days - after your receipt of the notice. - - Termination of your rights under this section does not terminate - the licenses of parties who have received copies or rights from you - under this License. If your rights have been terminated and not - permanently reinstated, receipt of a copy of some or all of the - same material does not give you any rights to use it. - - 10. FUTURE REVISIONS OF THIS LICENSE - - The Free Software Foundation may publish new, revised versions of - the GNU Free Documentation License from time to time. Such new - versions will be similar in spirit to the present version, but may - differ in detail to address new problems or concerns. See - . - - Each version of the License is given a distinguishing version - number. If the Document specifies that a particular numbered - version of this License "or any later version" applies to it, you - have the option of following the terms and conditions either of - that specified version or of any later version that has been - published (not as a draft) by the Free Software Foundation. If the - Document does not specify a version number of this License, you may - choose any version ever published (not as a draft) by the Free - Software Foundation. If the Document specifies that a proxy can - decide which future versions of this License can be used, that - proxy's public statement of acceptance of a version permanently - authorizes you to choose that version for the Document. - - 11. RELICENSING - - "Massive Multiauthor Collaboration Site" (or "MMC Site") means any - World Wide Web server that publishes copyrightable works and also - provides prominent facilities for anybody to edit those works. A - public wiki that anybody can edit is an example of such a server. - A "Massive Multiauthor Collaboration" (or "MMC") contained in the - site means any set of copyrightable works thus published on the MMC - site. - - "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0 - license published by Creative Commons Corporation, a not-for-profit - corporation with a principal place of business in San Francisco, - California, as well as future copyleft versions of that license - published by that same organization. - - "Incorporate" means to publish or republish a Document, in whole or - in part, as part of another Document. - - An MMC is "eligible for relicensing" if it is licensed under this - License, and if all works that were first published under this - License somewhere other than this MMC, and subsequently - incorporated in whole or in part into the MMC, (1) had no cover - texts or invariant sections, and (2) were thus incorporated prior - to November 1, 2008. - - The operator of an MMC Site may republish an MMC contained in the - site under CC-BY-SA on the same site at any time before August 1, - 2009, provided the MMC is eligible for relicensing. - -ADDENDUM: How to use this License for your documents -==================================================== - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and license -notices just after the title page: - - Copyright (C) YEAR YOUR NAME. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.3 - or any later version published by the Free Software Foundation; - with no Invariant Sections, no Front-Cover Texts, and no Back-Cover - Texts. A copy of the license is included in the section entitled ``GNU - Free Documentation License''. - - If you have Invariant Sections, Front-Cover Texts and Back-Cover -Texts, replace the "with...Texts." line with this: - - with the Invariant Sections being LIST THEIR TITLES, with - the Front-Cover Texts being LIST, and with the Back-Cover Texts - being LIST. - - If you have Invariant Sections without Cover Texts, or some other -combination of the three, merge those two alternatives to suit the -situation. - - If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of free -software license, such as the GNU General Public License, to permit -their use in free software. - - -File: standards.info, Node: Index, Prev: GNU Free Documentation License, Up: Top - -Index -***** - -[index] -* Menu: - -* '#endif', commenting: Comments. (line 60) -* '--help' output: --help. (line 6) -* '--version' output: --version. (line 6) -* '-Wall' compiler option: Syntactic Conventions. - (line 10) -* accepting contributions: Contributions. (line 6) -* address for bug reports: --help. (line 11) -* ANSI C standard: Standard C. (line 6) -* arbitrary limits on data: Semantics. (line 6) -* ASCII characters: Character Set. (line 6) -* autoconf: System Portability. (line 23) -* avoiding proprietary code: Reading Non-Free Code. - (line 6) -* behavior, dependent on program's name: User Interfaces. (line 6) -* binary packages: Install Command Categories. - (line 80) -* bindir: Directory Variables. (line 54) -* braces, in C source: Formatting. (line 6) -* bug reports: --help. (line 11) -* 'bug-standards@gnu.org' email address: Preface. (line 30) -* canonical name of a program: --version. (line 12) -* casting pointers to integers: CPU Portability. (line 88) -* CGI programs, standard options for: Command-Line Interfaces. - (line 31) -* change logs: Change Logs. (line 6) -* change logs, conditional changes: Conditional Changes. (line 6) -* change logs, style: Style of Change Logs. - (line 6) -* character set: Character Set. (line 6) -* command-line arguments, decoding: Semantics. (line 46) -* command-line interface: Command-Line Interfaces. - (line 6) -* commenting: Comments. (line 6) -* compatibility with C and POSIX standards: Compatibility. (line 6) -* compiler warnings: Syntactic Conventions. - (line 10) -* conditional changes, and change logs: Conditional Changes. (line 6) -* conditionals, comments for: Comments. (line 60) -* configure: Configuration. (line 6) -* control-L: Formatting. (line 118) -* conventions for makefiles: Makefile Conventions. - (line 6) -* CORBA: Graphical Interfaces. - (line 16) -* credits for manuals: Manual Credits. (line 6) -* D-bus: Graphical Interfaces. - (line 16) -* data types, and portability: CPU Portability. (line 6) -* declaration for system functions: System Functions. (line 21) -* DESTDIR: DESTDIR. (line 6) -* documentation: Documentation. (line 6) -* doschk: Names. (line 38) -* downloading this manual: Preface. (line 14) -* encodings: Character Set. (line 6) -* error messages: Semantics. (line 19) -* error messages, formatting: Errors. (line 6) -* exec_prefix: Directory Variables. (line 36) -* expressions, splitting: Formatting. (line 81) -* FDL, GNU Free Documentation License: GNU Free Documentation License. - (line 6) -* file usage: File Usage. (line 6) -* file-name limitations: Names. (line 38) -* formatting error messages: Errors. (line 6) -* formatting source code: Formatting. (line 6) -* formfeed: Formatting. (line 118) -* function argument, declaring: Syntactic Conventions. - (line 6) -* function prototypes: Standard C. (line 17) -* getopt: Command-Line Interfaces. - (line 6) -* gettext: Internationalization. - (line 6) -* GNOME: Graphical Interfaces. - (line 16) -* GNOME and Guile: Source Language. (line 37) -* gnustandards project repository: Preface. (line 30) -* 'gnustandards-commit@gnu.org' mailing list: Preface. (line 24) -* graphical user interface: Graphical Interfaces. - (line 6) -* grave accent: Quote Characters. (line 6) -* GTK+: Graphical Interfaces. - (line 6) -* Guile: Source Language. (line 37) -* implicit 'int': Syntactic Conventions. - (line 6) -* impossible conditions: Semantics. (line 70) -* installations, staged: DESTDIR. (line 6) -* interface styles: Graphical Interfaces. - (line 6) -* internationalization: Internationalization. - (line 6) -* keyboard interface: Graphical Interfaces. - (line 16) -* LDAP: OID Allocations. (line 6) -* left quote: Quote Characters. (line 6) -* legal aspects: Legal Issues. (line 6) -* legal papers: Contributions. (line 6) -* libexecdir: Directory Variables. (line 67) -* libraries: Libraries. (line 6) -* library functions, and portability: System Functions. (line 6) -* library interface: Graphical Interfaces. - (line 16) -* license for manuals: License for Manuals. (line 6) -* lint: Syntactic Conventions. - (line 109) -* locale-specific quote characters: Quote Characters. (line 6) -* long option names: Option Table. (line 6) -* long-named options: Command-Line Interfaces. - (line 12) -* makefile, conventions for: Makefile Conventions. - (line 6) -* 'malloc' return value: Semantics. (line 25) -* man pages: Man Pages. (line 6) -* manual structure: Manual Structure Details. - (line 6) -* memory allocation failure: Semantics. (line 25) -* memory usage: Memory Usage. (line 6) -* message text, and internationalization: Internationalization. - (line 29) -* mmap: Mmap. (line 6) -* multiple variables in a line: Syntactic Conventions. - (line 35) -* names of variables, functions, and files: Names. (line 6) -* 'NEWS' file: NEWS File. (line 6) -* non-ASCII characters: Character Set. (line 6) -* non-POSIX systems, and portability: System Portability. (line 32) -* non-standard extensions: Using Extensions. (line 6) -* 'NUL' characters: Semantics. (line 11) -* OID allocations for GNU: OID Allocations. (line 6) -* open brace: Formatting. (line 6) -* optional features, configure-time: Configuration. (line 97) -* options for compatibility: Compatibility. (line 14) -* options, standard command-line: Command-Line Interfaces. - (line 31) -* output device and program's behavior: User Interfaces. (line 13) -* packaging: Releases. (line 6) -* PATH_INFO, specifying standard options as: Command-Line Interfaces. - (line 31) -* portability, and data types: CPU Portability. (line 6) -* portability, and library functions: System Functions. (line 6) -* portability, between system types: System Portability. (line 6) -* POSIX compatibility: Compatibility. (line 6) -* 'POSIXLY_CORRECT', environment variable: Compatibility. (line 21) -* post-installation commands: Install Command Categories. - (line 6) -* pre-installation commands: Install Command Categories. - (line 6) -* prefix: Directory Variables. (line 26) -* program configuration: Configuration. (line 6) -* program design: Design Advice. (line 6) -* program name and its behavior: User Interfaces. (line 6) -* program's canonical name: --version. (line 12) -* programming languages: Source Language. (line 6) -* proprietary programs: Reading Non-Free Code. - (line 6) -* quote characters: Quote Characters. (line 6) -* 'README' file: Releases. (line 21) -* references to non-free material: References. (line 6) -* releasing: Managing Releases. (line 6) -* Savannah repository for gnustandards: Preface. (line 30) -* sbindir: Directory Variables. (line 60) -* signal handling: Semantics. (line 59) -* SNMP: OID Allocations. (line 6) -* spaces before open-paren: Formatting. (line 75) -* staged installs: DESTDIR. (line 6) -* standard command-line options: Command-Line Interfaces. - (line 31) -* standards for makefiles: Makefile Conventions. - (line 6) -* string library functions: System Functions. (line 54) -* syntactic conventions: Syntactic Conventions. - (line 6) -* table of long options: Option Table. (line 6) -* temporary files: Semantics. (line 84) -* temporary variables: Syntactic Conventions. - (line 23) -* 'texinfo.tex', in a distribution: Releases. (line 70) -* 'TMPDIR' environment variable: Semantics. (line 84) -* trademarks: Trademarks. (line 6) -* user interface styles: Graphical Interfaces. - (line 6) -* where to obtain 'standards.texi': Preface. (line 14) -* X.509: OID Allocations. (line 6) - - - -Tag Table: -Node: Top808 -Node: Preface2083 -Node: Legal Issues4784 -Node: Reading Non-Free Code5254 -Node: Contributions6983 -Node: Trademarks9221 -Node: Design Advice10855 -Node: Source Language11447 -Node: Compatibility13566 -Node: Using Extensions15194 -Node: Standard C16771 -Node: Conditional Compilation19174 -Node: Program Behavior20572 -Node: Non-GNU Standards21688 -Node: Semantics23969 -Node: Libraries28689 -Node: Errors29934 -Node: User Interfaces32428 -Node: Graphical Interfaces34033 -Node: Command-Line Interfaces35216 -Node: --version37246 -Node: --help42965 -Node: Option Table43838 -Node: OID Allocations58793 -Node: Memory Usage60590 -Node: File Usage61626 -Node: Writing C62376 -Node: Formatting63346 -Node: Comments67635 -Node: Syntactic Conventions71186 -Node: Names74648 -Node: System Portability76860 -Node: CPU Portability79751 -Node: System Functions83653 -Node: Internationalization88845 -Node: Character Set92839 -Node: Quote Characters93652 -Node: Mmap95172 -Node: Documentation95880 -Node: GNU Manuals96986 -Node: Doc Strings and Manuals102724 -Node: Manual Structure Details104277 -Node: License for Manuals105695 -Node: Manual Credits106668 -Node: Printed Manuals107061 -Node: NEWS File107747 -Node: Change Logs108425 -Node: Change Log Concepts109179 -Node: Style of Change Logs111282 -Node: Simple Changes113782 -Node: Conditional Changes115224 -Node: Indicating the Part Changed116646 -Node: Man Pages117173 -Node: Reading other Manuals119347 -Node: Managing Releases120138 -Node: Configuration120918 -Node: Makefile Conventions129581 -Node: Makefile Basics130463 -Node: Utilities in Makefiles133637 -Node: Command Variables135783 -Node: DESTDIR139006 -Node: Directory Variables141155 -Node: Standard Targets155640 -Ref: Standard Targets-Footnote-1169156 -Node: Install Command Categories169257 -Node: Releases173790 -Node: References177794 -Node: GNU Free Documentation License183640 -Node: Index208788 - -End Tag Table diff --git a/libc/xtensa-lx106-elf/include/_newlib_version.h b/libc/xtensa-lx106-elf/include/_newlib_version.h new file mode 100644 index 0000000..73b527e --- /dev/null +++ b/libc/xtensa-lx106-elf/include/_newlib_version.h @@ -0,0 +1,12 @@ +/* _newlib_version.h. Generated from _newlib_version.hin by configure. */ +/* Version macros for internal and downstream use. */ +#ifndef _NEWLIB_VERSION_H__ +#define _NEWLIB_VERSION_H__ 1 + +#define _NEWLIB_VERSION "2.5.0" +#define __NEWLIB__ 2 +#define __NEWLIB_MINOR__ 5 +#define __NEWLIB_PATCHLEVEL__ 0 + +#endif /* !_NEWLIB_VERSION_H__ */ + diff --git a/libc/xtensa-lx106-elf/include/complex.h b/libc/xtensa-lx106-elf/include/complex.h index 969b20e..0a3ea97 100644 --- a/libc/xtensa-lx106-elf/include/complex.h +++ b/libc/xtensa-lx106-elf/include/complex.h @@ -24,10 +24,12 @@ float complex cacosf(float complex); /* 7.3.5.2 The casin functions */ double complex casin(double complex); float complex casinf(float complex); +long double complex casinl(long double complex); /* 7.3.5.1 The catan functions */ double complex catan(double complex); float complex catanf(float complex); +long double complex catanl(long double complex); /* 7.3.5.1 The ccos functions */ double complex ccos(double complex); @@ -74,6 +76,7 @@ float complex cexpf(float complex); /* 7.3.7.2 The clog functions */ double complex clog(double complex); float complex clogf(float complex); +long double complex clogl(long double complex); /* 7.3.8 Power and absolute-value functions */ /* 7.3.8.1 The cabs functions */ @@ -83,6 +86,7 @@ float complex clogf(float complex); float cabsf(float complex) __RENAME(__c99_cabsf); #endif */ +long double cabsl(long double complex) ; double cabs(double complex) ; float cabsf(float complex) ; @@ -93,31 +97,56 @@ float complex cpowf(float complex, float complex); /* 7.3.8.3 The csqrt functions */ double complex csqrt(double complex); float complex csqrtf(float complex); +long double complex csqrtl(long double complex); /* 7.3.9 Manipulation functions */ /* 7.3.9.1 The carg functions */ double carg(double complex); float cargf(float complex); +long double cargl(long double complex); /* 7.3.9.2 The cimag functions */ double cimag(double complex); float cimagf(float complex); -/*long double cimagl(long double complex); */ +long double cimagl(long double complex); /* 7.3.9.3 The conj functions */ double complex conj(double complex); float complex conjf(float complex); -/*long double complex conjl(long double complex); */ /* 7.3.9.4 The cproj functions */ double complex cproj(double complex); float complex cprojf(float complex); -/*long double complex cprojl(long double complex); */ /* 7.3.9.5 The creal functions */ double creal(double complex); float crealf(float complex); -/*long double creall(long double complex); */ +long double creall(long double complex); + +#if __GNU_VISIBLE +double complex clog10(double complex); +float complex clog10f(float complex); +#endif + +#if defined(__CYGWIN__) +long double complex cacosl(long double complex); +long double complex ccosl(long double complex); +long double complex csinl(long double complex); +long double complex ctanl(long double complex); +long double complex cacoshl(long double complex); +long double complex casinhl(long double complex); +long double complex catanhl(long double complex); +long double complex ccoshl(long double complex); +long double complex csinhl(long double complex); +long double complex ctanhl(long double complex); +long double complex cexpl(long double complex); +long double complex cpowl(long double complex, long double complex); +long double complex conjl(long double complex); +long double complex cprojl(long double complex); +#if __GNU_VISIBLE +long double complex clog10l(long double complex); +#endif +#endif /* __CYGWIN__ */ __END_DECLS diff --git a/libc/xtensa-lx106-elf/include/cpio.h b/libc/xtensa-lx106-elf/include/cpio.h new file mode 100644 index 0000000..99860b2 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/cpio.h @@ -0,0 +1,30 @@ +/* POSIX.1 symbolic constants for c_mode field of cpio archive format */ + +#ifndef _CPIO_H +#define _CPIO_H + +#define C_IRUSR 0000400 /* Read by owner */ +#define C_IWUSR 0000200 /* Write by owner */ +#define C_IXUSR 0000100 /* Execute by owner */ +#define C_IRGRP 0000040 /* Read by group */ +#define C_IWGRP 0000020 /* Write by group */ +#define C_IXGRP 0000010 /* Execute by group */ +#define C_IROTH 0000004 /* Read by others */ +#define C_IWOTH 0000002 /* Write by others */ +#define C_IXOTH 0000001 /* Execute by others */ +#define C_ISUID 0004000 /* Set user ID */ +#define C_ISGID 0002000 /* Set group ID */ +#define C_ISVTX 0001000 /* On directories, restricted deletion flag */ + +#define C_ISDIR 0040000 /* Directory */ +#define C_ISFIFO 0010000 /* FIFO */ +#define C_ISREG 0100000 /* Regular file */ +#define C_ISBLK 0060000 /* Block special */ +#define C_ISCHR 0020000 /* Character special */ +#define C_ISCTG 0110000 /* Reserved */ +#define C_ISLNK 0120000 /* Symbolic link */ +#define C_ISSOCK 0140000 /* Socket */ + +#define MAGIC "070707" + +#endif /* _CPIO_H */ diff --git a/libc/xtensa-lx106-elf/include/ctype.h b/libc/xtensa-lx106-elf/include/ctype.h index 56ad5ab..06458cb 100644 --- a/libc/xtensa-lx106-elf/include/ctype.h +++ b/libc/xtensa-lx106-elf/include/ctype.h @@ -2,6 +2,11 @@ #define _CTYPE_H_ #include "_ansi.h" +#include + +#if __POSIX_VISIBLE >= 200809 || __MISC_VISIBLE || defined (_COMPILING_NEWLIB) +#include +#endif _BEGIN_STD_C @@ -19,17 +24,39 @@ int _EXFUN(isxdigit,(int __c)); int _EXFUN(tolower, (int __c)); int _EXFUN(toupper, (int __c)); -#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L +#if __ISO_C_VISIBLE >= 1999 int _EXFUN(isblank, (int __c)); #endif -#ifndef __STRICT_ANSI__ +#if __MISC_VISIBLE || __XSI_VISIBLE int _EXFUN(isascii, (int __c)); int _EXFUN(toascii, (int __c)); #define _tolower(__c) ((unsigned char)(__c) - 'A' + 'a') #define _toupper(__c) ((unsigned char)(__c) - 'a' + 'A') #endif +#if __POSIX_VISIBLE >= 200809 +extern int isalnum_l (int __c, locale_t __l); +extern int isalpha_l (int __c, locale_t __l); +extern int isblank_l (int __c, locale_t __l); +extern int iscntrl_l (int __c, locale_t __l); +extern int isdigit_l (int __c, locale_t __l); +extern int isgraph_l (int __c, locale_t __l); +extern int islower_l (int __c, locale_t __l); +extern int isprint_l (int __c, locale_t __l); +extern int ispunct_l (int __c, locale_t __l); +extern int isspace_l (int __c, locale_t __l); +extern int isupper_l (int __c, locale_t __l); +extern int isxdigit_l(int __c, locale_t __l); +extern int tolower_l (int __c, locale_t __l); +extern int toupper_l (int __c, locale_t __l); +#endif + +#if __MISC_VISIBLE +extern int isascii_l (int __c, locale_t __l); +extern int toascii_l (int __c, locale_t __l); +#endif + #define _U 01 #define _L 02 #define _N 04 @@ -39,22 +66,20 @@ int _EXFUN(toascii, (int __c)); #define _X 0100 #define _B 0200 -#ifndef _MB_CAPABLE -_CONST -#endif -extern __IMPORT char *__ctype_ptr__; +const char *__locale_ctype_ptr (void); +# define __CTYPE_PTR (__locale_ctype_ptr ()) #ifndef __cplusplus /* These macros are intentionally written in a manner that will trigger a gcc -Wall warning if the user mistakenly passes a 'char' instead of an int containing an 'unsigned char'. Note that the sizeof will - always be 1, which is what we want for mapping EOF to __ctype_ptr__[0]; + always be 1, which is what we want for mapping EOF to __CTYPE_PTR[0]; the use of a raw index inside the sizeof triggers the gcc warning if __c was of type char, and sizeof masks side effects of the extra __c. - Meanwhile, the real index to __ctype_ptr__+1 must be cast to int, + Meanwhile, the real index to __CTYPE_PTR+1 must be cast to int, since isalpha(0x100000001LL) must equal isalpha(1), rather than being an out-of-bounds reference on a 64-bit machine. */ -#define __ctype_lookup(__c) ((__ctype_ptr__+sizeof(""[__c]))[(int)(__c)]) +#define __ctype_lookup(__c) ((__CTYPE_PTR+sizeof(""[__c]))[(int)(__c)]) #define isalpha(__c) (__ctype_lookup(__c)&(_U|_L)) #define isupper(__c) ((__ctype_lookup(__c)&(_U|_L))==_U) @@ -68,13 +93,45 @@ extern __IMPORT char *__ctype_ptr__; #define isgraph(__c) (__ctype_lookup(__c)&(_P|_U|_L|_N)) #define iscntrl(__c) (__ctype_lookup(__c)&_C) -#if defined(__GNUC__) && \ - (!defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901L) +#if defined(__GNUC__) && __ISO_C_VISIBLE >= 1999 #define isblank(__c) \ __extension__ ({ __typeof__ (__c) __x = (__c); \ (__ctype_lookup(__x)&_B) || (int) (__x) == '\t';}) #endif +#if __POSIX_VISIBLE >= 200809 +const char *__locale_ctype_ptr_l (locale_t); +#define __ctype_lookup_l(__c,__l) ((__locale_ctype_ptr_l(__l)+sizeof(""[__c]))[(int)(__c)]) + +#define isalpha_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_U|_L)) +#define isupper_l(__c,__l) ((__ctype_lookup_l(__c,__l)&(_U|_L))==_U) +#define islower_l(__c,__l) ((__ctype_lookup_l(__c,__l)&(_U|_L))==_L) +#define isdigit_l(__c,__l) (__ctype_lookup_l(__c,__l)&_N) +#define isxdigit_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_X|_N)) +#define isspace_l(__c,__l) (__ctype_lookup_l(__c,__l)&_S) +#define ispunct_l(__c,__l) (__ctype_lookup_l(__c,__l)&_P) +#define isalnum_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_U|_L|_N)) +#define isprint_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_P|_U|_L|_N|_B)) +#define isgraph_l(__c,__l) (__ctype_lookup_l(__c,__l)&(_P|_U|_L|_N)) +#define iscntrl_l(__c,__l) (__ctype_lookup_l(__c,__l)&_C) + +#if defined(__GNUC__) +#define isblank_l(__c, __l) \ + __extension__ ({ __typeof__ (__c) __x = (__c); \ + (__ctype_lookup_l(__x,__l)&_B) || (int) (__x) == '\t';}) +#endif + +#endif /* __POSIX_VISIBLE >= 200809 */ + +#if __MISC_VISIBLE || __XSI_VISIBLE +#define isascii(__c) ((unsigned)(__c)<=0177) +#define toascii(__c) ((__c)&0177) +#endif + +#if __MISC_VISIBLE +#define isascii_l(__c,__l) ((__l),(unsigned)(__c)<=0177) +#define toascii_l(__c,__l) ((__l),(__c)&0177) +#endif /* Non-gcc versions will get the library versions, and will be slightly slower. These macros are not NLS-aware so they are @@ -92,18 +149,17 @@ extern __IMPORT char *__ctype_ptr__; function. */ # define toupper(__c) \ __extension__ ({ __typeof__ (__c) __x = (__c); \ - (void) __ctype_ptr__[__x]; (toupper) (__x);}) + (void) __CTYPE_PTR[__x]; (toupper) (__x);}) # define tolower(__c) \ __extension__ ({ __typeof__ (__c) __x = (__c); \ - (void) __ctype_ptr__[__x]; (tolower) (__x);}) + (void) __CTYPE_PTR[__x]; (tolower) (__x);}) # endif /* _MB_EXTENDED_CHARSETS* */ # endif /* __GNUC__ */ -#endif /* !__cplusplus */ -#ifndef __STRICT_ANSI__ -#define isascii(__c) ((unsigned)(__c)<=0177) -#define toascii(__c) ((__c)&0177) -#endif +#if __POSIX_VISIBLE >= 200809 +#endif /* __POSIX_VISIBLE >= 200809 */ + +#endif /* !__cplusplus */ /* For C++ backward-compatibility only. */ extern __IMPORT _CONST char _ctype_[]; diff --git a/libc/xtensa-lx106-elf/include/devctl.h b/libc/xtensa-lx106-elf/include/devctl.h new file mode 100644 index 0000000..f6055fb --- /dev/null +++ b/libc/xtensa-lx106-elf/include/devctl.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Joel Sherrill . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _POSIX_DEVCTL_h_ +#define _POSIX_DEVCTL_h_ + +/* + * The posix_devctl() method is defined by POSIX 1003.26-2003. Aside + * from the single method, it adds the following requirements: + * + * + define _POSIX_26_VERSION to 200312L + * + add _SC_POSIX_26_VERSION in . Return _POSIX_26_VERSION + * + application must define _POSIX_26_C_SOURCE to use posix_devctl(). + * + posix_devctl() is prototyped in + */ + +#ifdef _POSIX_26_C_SOURCE +#include + +int posix_devctl( + int fd, + int dcmd, + void *__restrict dev_data_ptr, + size_t nbyte, + int *__restrict dev_info_ptr +); +#endif + +#endif diff --git a/libc/xtensa-lx106-elf/include/dirent.h b/libc/xtensa-lx106-elf/include/dirent.h index 6fefc03..6135b9f 100644 --- a/libc/xtensa-lx106-elf/include/dirent.h +++ b/libc/xtensa-lx106-elf/include/dirent.h @@ -3,9 +3,10 @@ #ifdef __cplusplus extern "C" { #endif +#include #include -#if !defined(MAXNAMLEN) && !defined(_POSIX_SOURCE) +#if !defined(MAXNAMLEN) && __BSD_VISIBLE #define MAXNAMLEN 1024 #endif diff --git a/libc/xtensa-lx106-elf/include/fnmatch.h b/libc/xtensa-lx106-elf/include/fnmatch.h index 06311fc..a94e923 100644 --- a/libc/xtensa-lx106-elf/include/fnmatch.h +++ b/libc/xtensa-lx106-elf/include/fnmatch.h @@ -33,21 +33,21 @@ #ifndef _FNMATCH_H_ #define _FNMATCH_H_ +#include + #define FNM_NOMATCH 1 /* Match failed. */ #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ #define FNM_PERIOD 0x04 /* Period must be matched by period. */ -#if defined(_GNU_SOURCE) || !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE) +#if __GNU_VISIBLE #define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */ #define FNM_IGNORECASE FNM_CASEFOLD #define FNM_FILE_NAME FNM_PATHNAME #endif -#include - __BEGIN_DECLS int fnmatch(const char *, const char *, int); __END_DECLS diff --git a/libc/xtensa-lx106-elf/include/grp.h b/libc/xtensa-lx106-elf/include/grp.h index c3a5a67..6a26564 100644 --- a/libc/xtensa-lx106-elf/include/grp.h +++ b/libc/xtensa-lx106-elf/include/grp.h @@ -49,7 +49,7 @@ #include #endif -#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) +#if __BSD_VISIBLE #define _PATH_GROUP "/etc/group" #endif @@ -67,25 +67,20 @@ extern "C" { #ifndef __INSIDE_CYGWIN__ struct group *getgrgid (gid_t); struct group *getgrnam (const char *); +#if __MISC_VISIBLE || __POSIX_VISIBLE int getgrnam_r (const char *, struct group *, char *, size_t, struct group **); int getgrgid_r (gid_t, struct group *, char *, size_t, struct group **); -#ifndef _POSIX_SOURCE +#endif /* __MISC_VISIBLE || __POSIX_VISIBLE */ +#if __MISC_VISIBLE || __XSI_VISIBLE >= 4 struct group *getgrent (void); void setgrent (void); void endgrent (void); -#ifndef __CYGWIN__ -void setgrfile (const char *); -#endif /* !__CYGWIN__ */ -#ifndef _XOPEN_SOURCE -#ifndef __CYGWIN__ -char *group_from_gid (gid_t, int); -int setgroupent (int); -#endif /* !__CYGWIN__ */ +#endif /* __MISC_VISIBLE || __XSI_VISIBLE >= 4 */ +#if __BSD_VISIBLE int initgroups (const char *, gid_t); -#endif /* !_XOPEN_SOURCE */ -#endif /* !_POSIX_SOURCE */ +#endif /* __BSD_VISIBLE */ #endif /* !__INSIDE_CYGWIN__ */ #ifdef __cplusplus diff --git a/libc/xtensa-lx106-elf/include/ieeefp.h b/libc/xtensa-lx106-elf/include/ieeefp.h index 0b06fb7..2c04284 100644 --- a/libc/xtensa-lx106-elf/include/ieeefp.h +++ b/libc/xtensa-lx106-elf/include/ieeefp.h @@ -4,11 +4,12 @@ #include "_ansi.h" #include +#include _BEGIN_STD_C /* FIXME FIXME FIXME: - Neither of __ieee_{float,double}_shape_tape seem to be used anywhere + Neither of __ieee_{float,double}_shape_type seem to be used anywhere except in libm/test. If that is the case, please delete these from here. If that is not the case, please insert documentation here describing why they're needed. */ @@ -46,9 +47,7 @@ typedef union long aslong[2]; } __ieee_double_shape_type; -#endif - -#ifdef __IEEE_LITTLE_ENDIAN +#elif defined __IEEE_LITTLE_ENDIAN typedef union { @@ -92,7 +91,7 @@ typedef union } __ieee_double_shape_type; -#endif +#endif /* __IEEE_LITTLE_ENDIAN */ #ifdef __IEEE_BIG_ENDIAN @@ -118,9 +117,7 @@ typedef union } __ieee_float_shape_type; -#endif - -#ifdef __IEEE_LITTLE_ENDIAN +#elif defined __IEEE_LITTLE_ENDIAN typedef union { @@ -144,10 +141,70 @@ typedef union } __ieee_float_shape_type; +#endif /* __IEEE_LITTLE_ENDIAN */ + +#ifndef _LDBL_EQ_DBL + +#ifndef LDBL_MANT_DIG +#error "LDBL_MANT_DIG not defined - should be found in float.h" + +#elif LDBL_MANT_DIG == DBL_MANT_DIG +#error "double and long double are the same size but LDBL_EQ_DBL is not defined" + +#elif LDBL_MANT_DIG == 53 +/* This happens when doubles are 32-bits and long doubles are 64-bits. */ +#define EXT_EXPBITS 11 +#define EXT_FRACHBITS 20 +#define EXT_FRACLBITS 32 +#define __ieee_ext_field_type unsigned long + +#elif LDBL_MANT_DIG == 64 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define __ieee_ext_field_type unsigned int + +#elif LDBL_MANT_DIG == 65 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define __ieee_ext_field_type unsigned int + +#elif LDBL_MANT_DIG == 112 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 48 +#define EXT_FRACLBITS 64 +#define __ieee_ext_field_type unsigned long long + +#elif LDBL_MANT_DIG == 113 +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 48 +#define EXT_FRACLBITS 64 +#define __ieee_ext_field_type unsigned long long + +#else +#error Unsupported value for LDBL_MANT_DIG #endif +#define EXT_EXP_INFNAN ((1 << EXT_EXPBITS) - 1) /* 32767 */ +#define EXT_EXP_BIAS ((1 << (EXT_EXPBITS - 1)) - 1) /* 16383 */ +#define EXT_FRACBITS (EXT_FRACLBITS + EXT_FRACHBITS) +typedef struct ieee_ext +{ + __ieee_ext_field_type ext_fracl : EXT_FRACLBITS; + __ieee_ext_field_type ext_frach : EXT_FRACHBITS; + __ieee_ext_field_type ext_exp : EXT_EXPBITS; + __ieee_ext_field_type ext_sign : 1; +} ieee_ext; +typedef union ieee_ext_u +{ + long double extu_ld; + struct ieee_ext extu_ext; +} ieee_ext_u; + +#endif /* ! _LDBL_EQ_DBL */ /* FLOATING ROUNDING */ @@ -184,19 +241,6 @@ typedef int fp_rdi; fp_rdi _EXFUN(fpgetroundtoi,(void)); fp_rdi _EXFUN(fpsetroundtoi,(fp_rdi)); -#undef isnan -#undef isinf - -int _EXFUN(isnan, (double)); -int _EXFUN(isinf, (double)); -int _EXFUN(finite, (double)); - - - -int _EXFUN(isnanf, (float)); -int _EXFUN(isinff, (float)); -int _EXFUN(finitef, (float)); - #define __IEEE_DBL_EXPBIAS 1023 #define __IEEE_FLT_EXPBIAS 127 @@ -213,22 +257,17 @@ int _EXFUN(finitef, (float)); #define __IEEE_DBL_NAN_EXP 0x7ff #define __IEEE_FLT_NAN_EXP 0xff -#ifndef __ieeefp_isnanf -#define __ieeefp_isnanf(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \ - ((*(long *)&(x) & 0x007fffffL)!=0000000000L)) -#endif +#ifdef __ieeefp_isnanf #define isnanf(x) __ieeefp_isnanf(x) - -#ifndef __ieeefp_isinff -#define __ieeefp_isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \ - ((*(long *)&(x) & 0x007fffffL)==0000000000L)) #endif + +#ifdef __ieeefp_isinff #define isinff(x) __ieeefp_isinff(x) - -#ifndef __ieeefp_finitef -#define __ieeefp_finitef(x) (((*(long *)&(x) & 0x7f800000L)!=0x7f800000L)) #endif + +#ifdef __ieeefp_finitef #define finitef(x) __ieeefp_finitef(x) +#endif #ifdef _DOUBLE_IS_32BITS #undef __IEEE_DBL_EXPBIAS diff --git a/libc/xtensa-lx106-elf/include/inttypes.h b/libc/xtensa-lx106-elf/include/inttypes.h index 39bf135..694ba8f 100644 --- a/libc/xtensa-lx106-elf/include/inttypes.h +++ b/libc/xtensa-lx106-elf/include/inttypes.h @@ -14,15 +14,23 @@ #define _INTTYPES_H #include +#include #include +#include "_ansi.h" #include #define __need_wchar_t #include +#if __BSD_VISIBLE +#include +#endif + #define __STRINGIFY(a) #a /* 8-bit types */ -#define __PRI8(x) __STRINGIFY(x) +#define __PRI8(x) __INT8 __STRINGIFY(x) +#define __PRI8LEAST(x) __LEAST8 __STRINGIFY(x) +#define __PRI8FAST(x) __FAST8 __STRINGIFY(x) /* NOTICE: scanning 8-bit types requires use of the hh specifier * which is only supported on newlib platforms that @@ -35,7 +43,9 @@ */ #if defined(_WANT_IO_C99_FORMATS) - #define __SCN8(x) __STRINGIFY(hh##x) + #define __SCN8(x) __INT8 __STRINGIFY(x) + #define __SCN8LEAST(x) __LEAST8 __STRINGIFY(x) + #define __SCN8FAST(x) __FAST8 __STRINGIFY(x) #endif /* _WANT_IO_C99_FORMATS */ @@ -58,45 +68,49 @@ #endif /* _WANT_IO_C99_FORMATS */ -#define PRIdLEAST8 __PRI8(d) -#define PRIiLEAST8 __PRI8(i) -#define PRIoLEAST8 __PRI8(o) -#define PRIuLEAST8 __PRI8(u) -#define PRIxLEAST8 __PRI8(x) -#define PRIXLEAST8 __PRI8(X) +#define PRIdLEAST8 __PRI8LEAST(d) +#define PRIiLEAST8 __PRI8LEAST(i) +#define PRIoLEAST8 __PRI8LEAST(o) +#define PRIuLEAST8 __PRI8LEAST(u) +#define PRIxLEAST8 __PRI8LEAST(x) +#define PRIXLEAST8 __PRI8LEAST(X) /* Macros below are only enabled for a newlib built with C99 I/O format support. */ #if defined(_WANT_IO_C99_FORMATS) - #define SCNdLEAST8 __SCN8(d) - #define SCNiLEAST8 __SCN8(i) - #define SCNoLEAST8 __SCN8(o) - #define SCNuLEAST8 __SCN8(u) - #define SCNxLEAST8 __SCN8(x) + #define SCNdLEAST8 __SCN8LEAST(d) + #define SCNiLEAST8 __SCN8LEAST(i) + #define SCNoLEAST8 __SCN8LEAST(o) + #define SCNuLEAST8 __SCN8LEAST(u) + #define SCNxLEAST8 __SCN8LEAST(x) #endif /* _WANT_IO_C99_FORMATS */ -#define PRIdFAST8 __PRI8(d) -#define PRIiFAST8 __PRI8(i) -#define PRIoFAST8 __PRI8(o) -#define PRIuFAST8 __PRI8(u) -#define PRIxFAST8 __PRI8(x) -#define PRIXFAST8 __PRI8(X) +#define PRIdFAST8 __PRI8FAST(d) +#define PRIiFAST8 __PRI8FAST(i) +#define PRIoFAST8 __PRI8FAST(o) +#define PRIuFAST8 __PRI8FAST(u) +#define PRIxFAST8 __PRI8FAST(x) +#define PRIXFAST8 __PRI8FAST(X) /* Macros below are only enabled for a newlib built with C99 I/O format support. */ #if defined(_WANT_IO_C99_FORMATS) - #define SCNdFAST8 __SCN8(d) - #define SCNiFAST8 __SCN8(i) - #define SCNoFAST8 __SCN8(o) - #define SCNuFAST8 __SCN8(u) - #define SCNxFAST8 __SCN8(x) + #define SCNdFAST8 __SCN8FAST(d) + #define SCNiFAST8 __SCN8FAST(i) + #define SCNoFAST8 __SCN8FAST(o) + #define SCNuFAST8 __SCN8FAST(u) + #define SCNxFAST8 __SCN8FAST(x) #endif /* _WANT_IO_C99_FORMATS */ /* 16-bit types */ -#define __PRI16(x) __STRINGIFY(x) -#define __SCN16(x) __STRINGIFY(h##x) +#define __PRI16(x) __INT16 __STRINGIFY(x) +#define __PRI16LEAST(x) __LEAST16 __STRINGIFY(x) +#define __PRI16FAST(x) __FAST16 __STRINGIFY(x) +#define __SCN16(x) __INT16 __STRINGIFY(x) +#define __SCN16LEAST(x) __LEAST16 __STRINGIFY(x) +#define __SCN16FAST(x) __FAST16 __STRINGIFY(x) #define PRId16 __PRI16(d) @@ -113,41 +127,40 @@ #define SCNx16 __SCN16(x) -#define PRIdLEAST16 __PRI16(d) -#define PRIiLEAST16 __PRI16(i) -#define PRIoLEAST16 __PRI16(o) -#define PRIuLEAST16 __PRI16(u) -#define PRIxLEAST16 __PRI16(x) -#define PRIXLEAST16 __PRI16(X) +#define PRIdLEAST16 __PRI16LEAST(d) +#define PRIiLEAST16 __PRI16LEAST(i) +#define PRIoLEAST16 __PRI16LEAST(o) +#define PRIuLEAST16 __PRI16LEAST(u) +#define PRIxLEAST16 __PRI16LEAST(x) +#define PRIXLEAST16 __PRI16LEAST(X) -#define SCNdLEAST16 __SCN16(d) -#define SCNiLEAST16 __SCN16(i) -#define SCNoLEAST16 __SCN16(o) -#define SCNuLEAST16 __SCN16(u) -#define SCNxLEAST16 __SCN16(x) +#define SCNdLEAST16 __SCN16LEAST(d) +#define SCNiLEAST16 __SCN16LEAST(i) +#define SCNoLEAST16 __SCN16LEAST(o) +#define SCNuLEAST16 __SCN16LEAST(u) +#define SCNxLEAST16 __SCN16LEAST(x) -#define PRIdFAST16 __PRI16(d) -#define PRIiFAST16 __PRI16(i) -#define PRIoFAST16 __PRI16(o) -#define PRIuFAST16 __PRI16(u) -#define PRIxFAST16 __PRI16(x) -#define PRIXFAST16 __PRI16(X) +#define PRIdFAST16 __PRI16FAST(d) +#define PRIiFAST16 __PRI16FAST(i) +#define PRIoFAST16 __PRI16FAST(o) +#define PRIuFAST16 __PRI16FAST(u) +#define PRIxFAST16 __PRI16FAST(x) +#define PRIXFAST16 __PRI16FAST(X) -#define SCNdFAST16 __SCN16(d) -#define SCNiFAST16 __SCN16(i) -#define SCNoFAST16 __SCN16(o) -#define SCNuFAST16 __SCN16(u) -#define SCNxFAST16 __SCN16(x) +#define SCNdFAST16 __SCN16FAST(d) +#define SCNiFAST16 __SCN16FAST(i) +#define SCNoFAST16 __SCN16FAST(o) +#define SCNuFAST16 __SCN16FAST(u) +#define SCNxFAST16 __SCN16FAST(x) /* 32-bit types */ -#if __have_long32 -#define __PRI32(x) __STRINGIFY(l##x) -#define __SCN32(x) __STRINGIFY(l##x) -#else -#define __PRI32(x) __STRINGIFY(x) -#define __SCN32(x) __STRINGIFY(x) -#endif +#define __PRI32(x) __INT32 __STRINGIFY(x) +#define __SCN32(x) __INT32 __STRINGIFY(x) +#define __PRI32LEAST(x) __LEAST32 __STRINGIFY(x) +#define __SCN32LEAST(x) __LEAST32 __STRINGIFY(x) +#define __PRI32FAST(x) __FAST32 __STRINGIFY(x) +#define __SCN32FAST(x) __FAST32 __STRINGIFY(x) #define PRId32 __PRI32(d) #define PRIi32 __PRI32(i) @@ -163,46 +176,44 @@ #define SCNx32 __SCN32(x) -#define PRIdLEAST32 __PRI32(d) -#define PRIiLEAST32 __PRI32(i) -#define PRIoLEAST32 __PRI32(o) -#define PRIuLEAST32 __PRI32(u) -#define PRIxLEAST32 __PRI32(x) -#define PRIXLEAST32 __PRI32(X) +#define PRIdLEAST32 __PRI32LEAST(d) +#define PRIiLEAST32 __PRI32LEAST(i) +#define PRIoLEAST32 __PRI32LEAST(o) +#define PRIuLEAST32 __PRI32LEAST(u) +#define PRIxLEAST32 __PRI32LEAST(x) +#define PRIXLEAST32 __PRI32LEAST(X) -#define SCNdLEAST32 __SCN32(d) -#define SCNiLEAST32 __SCN32(i) -#define SCNoLEAST32 __SCN32(o) -#define SCNuLEAST32 __SCN32(u) -#define SCNxLEAST32 __SCN32(x) +#define SCNdLEAST32 __SCN32LEAST(d) +#define SCNiLEAST32 __SCN32LEAST(i) +#define SCNoLEAST32 __SCN32LEAST(o) +#define SCNuLEAST32 __SCN32LEAST(u) +#define SCNxLEAST32 __SCN32LEAST(x) -#define PRIdFAST32 __PRI32(d) -#define PRIiFAST32 __PRI32(i) -#define PRIoFAST32 __PRI32(o) -#define PRIuFAST32 __PRI32(u) -#define PRIxFAST32 __PRI32(x) -#define PRIXFAST32 __PRI32(X) +#define PRIdFAST32 __PRI32FAST(d) +#define PRIiFAST32 __PRI32FAST(i) +#define PRIoFAST32 __PRI32FAST(o) +#define PRIuFAST32 __PRI32FAST(u) +#define PRIxFAST32 __PRI32FAST(x) +#define PRIXFAST32 __PRI32FAST(X) -#define SCNdFAST32 __SCN32(d) -#define SCNiFAST32 __SCN32(i) -#define SCNoFAST32 __SCN32(o) -#define SCNuFAST32 __SCN32(u) -#define SCNxFAST32 __SCN32(x) +#define SCNdFAST32 __SCN32FAST(d) +#define SCNiFAST32 __SCN32FAST(i) +#define SCNoFAST32 __SCN32FAST(o) +#define SCNuFAST32 __SCN32FAST(u) +#define SCNxFAST32 __SCN32FAST(x) /* 64-bit types */ -#if __have_long64 -#define __PRI64(x) __STRINGIFY(l##x) -#define __SCN64(x) __STRINGIFY(l##x) -#elif __have_longlong64 -#define __PRI64(x) __STRINGIFY(ll##x) -#define __SCN64(x) __STRINGIFY(ll##x) -#else -#define __PRI64(x) __STRINGIFY(x) -#define __SCN64(x) __STRINGIFY(x) -#endif +#define __PRI64(x) __INT64 __STRINGIFY(x) +#define __SCN64(x) __INT64 __STRINGIFY(x) +#define __PRI64LEAST(x) __LEAST64 __STRINGIFY(x) +#define __SCN64LEAST(x) __LEAST64 __STRINGIFY(x) +#define __PRI64FAST(x) __FAST64 __STRINGIFY(x) +#define __SCN64FAST(x) __FAST64 __STRINGIFY(x) + +#if __int64_t_defined #define PRId64 __PRI64(d) #define PRIi64 __PRI64(i) #define PRIo64 __PRI64(o) @@ -215,34 +226,36 @@ #define SCNo64 __SCN64(o) #define SCNu64 __SCN64(u) #define SCNx64 __SCN64(x) +#endif -#if __int64_t_defined -#define PRIdLEAST64 __PRI64(d) -#define PRIiLEAST64 __PRI64(i) -#define PRIoLEAST64 __PRI64(o) -#define PRIuLEAST64 __PRI64(u) -#define PRIxLEAST64 __PRI64(x) -#define PRIXLEAST64 __PRI64(X) +#if __int_least64_t_defined +#define PRIdLEAST64 __PRI64LEAST(d) +#define PRIiLEAST64 __PRI64LEAST(i) +#define PRIoLEAST64 __PRI64LEAST(o) +#define PRIuLEAST64 __PRI64LEAST(u) +#define PRIxLEAST64 __PRI64LEAST(x) +#define PRIXLEAST64 __PRI64LEAST(X) -#define SCNdLEAST64 __SCN64(d) -#define SCNiLEAST64 __SCN64(i) -#define SCNoLEAST64 __SCN64(o) -#define SCNuLEAST64 __SCN64(u) -#define SCNxLEAST64 __SCN64(x) +#define SCNdLEAST64 __SCN64LEAST(d) +#define SCNiLEAST64 __SCN64LEAST(i) +#define SCNoLEAST64 __SCN64LEAST(o) +#define SCNuLEAST64 __SCN64LEAST(u) +#define SCNxLEAST64 __SCN64LEAST(x) +#endif +#if __int_fast64_t_defined +#define PRIdFAST64 __PRI64FAST(d) +#define PRIiFAST64 __PRI64FAST(i) +#define PRIoFAST64 __PRI64FAST(o) +#define PRIuFAST64 __PRI64FAST(u) +#define PRIxFAST64 __PRI64FAST(x) +#define PRIXFAST64 __PRI64FAST(X) -#define PRIdFAST64 __PRI64(d) -#define PRIiFAST64 __PRI64(i) -#define PRIoFAST64 __PRI64(o) -#define PRIuFAST64 __PRI64(u) -#define PRIxFAST64 __PRI64(x) -#define PRIXFAST64 __PRI64(X) - -#define SCNdFAST64 __SCN64(d) -#define SCNiFAST64 __SCN64(i) -#define SCNoFAST64 __SCN64(o) -#define SCNuFAST64 __SCN64(u) -#define SCNxFAST64 __SCN64(x) +#define SCNdFAST64 __SCN64FAST(d) +#define SCNiFAST64 __SCN64FAST(i) +#define SCNoFAST64 __SCN64FAST(o) +#define SCNuFAST64 __SCN64FAST(u) +#define SCNxFAST64 __SCN64FAST(x) #endif /* max-bit types */ @@ -271,10 +284,10 @@ #define SCNxMAX __SCNMAX(x) /* ptr types */ -#if defined(_UINTPTR_EQ_ULONGLONG) +#if defined (_INTPTR_EQ_LONGLONG) # define __PRIPTR(x) __STRINGIFY(ll##x) # define __SCNPTR(x) __STRINGIFY(ll##x) -#elif defined(_UINTPTR_EQ_ULONG) +#elif defined (_INTPTR_EQ_LONG) # define __PRIPTR(x) __STRINGIFY(l##x) # define __SCNPTR(x) __STRINGIFY(l##x) #else @@ -301,6 +314,8 @@ typedef struct { intmax_t rem; } imaxdiv_t; +struct _reent; + #ifdef __cplusplus extern "C" { #endif @@ -308,9 +323,20 @@ extern "C" { extern intmax_t imaxabs(intmax_t j); extern imaxdiv_t imaxdiv(intmax_t numer, intmax_t denomer); extern intmax_t strtoimax(const char *__restrict, char **__restrict, int); +extern intmax_t _strtoimax_r(struct _reent *, const char *__restrict, char **__restrict, int); extern uintmax_t strtoumax(const char *__restrict, char **__restrict, int); +extern uintmax_t _strtoumax_r(struct _reent *, const char *__restrict, char **__restrict, int); extern intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int); +extern intmax_t _wcstoimax_r(struct _reent *, const wchar_t *__restrict, wchar_t **__restrict, int); extern uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); +extern uintmax_t _wcstoumax_r(struct _reent *, const wchar_t *__restrict, wchar_t **__restrict, int); + +#if __BSD_VISIBLE +extern intmax_t strtoimax_l(const char *__restrict, char **_restrict, int, locale_t); +extern uintmax_t strtoumax_l(const char *__restrict, char **_restrict, int, locale_t); +extern intmax_t wcstoimax_l(const wchar_t *__restrict, wchar_t **_restrict, int, locale_t); +extern uintmax_t wcstoumax_l(const wchar_t *__restrict, wchar_t **_restrict, int, locale_t); +#endif #ifdef __cplusplus } diff --git a/libc/xtensa-lx106-elf/include/langinfo.h b/libc/xtensa-lx106-elf/include/langinfo.h index 9040ade..59381d6 100644 --- a/libc/xtensa-lx106-elf/include/langinfo.h +++ b/libc/xtensa-lx106-elf/include/langinfo.h @@ -32,6 +32,9 @@ #include #include #include +#if __POSIX_VISIBLE >= 200809 +#include +#endif typedef int nl_item; @@ -301,7 +304,7 @@ enum __nl_item _NL_COLLATE_CODESET, /* This MUST be the last entry since it's used to check for an array - index in nl_langinfo(). */ + index in nl_langinfo(). It also must not exceed _NL_LOCALE_NAME_BASE. */ _NL_LOCALE_EXTENDED_LAST_ENTRY #endif /* __HAVE_LOCALE_INFO_EXTENDED__ */ @@ -309,8 +312,19 @@ enum __nl_item }; +/* As an extension, nl_langinfo can retrive the name of a locale + category, with this mapping from setlocale() category (other than + LC_ALL) to nl_item. */ +#define _NL_LOCALE_NAME_BASE 100000 +#if __GNU_VISIBLE +#define NL_LOCALE_NAME(category) (_NL_LOCALE_NAME_BASE + (category)) +#endif + __BEGIN_DECLS -char *nl_langinfo(nl_item); +char *nl_langinfo (nl_item); +#if __POSIX_VISIBLE >= 200809 +char *nl_langinfo_l (nl_item, locale_t); +#endif __END_DECLS #endif /* !_LANGINFO_H_ */ diff --git a/libc/xtensa-lx106-elf/include/libgen.h b/libc/xtensa-lx106-elf/include/libgen.h index abfab0e..3c717c5 100644 --- a/libc/xtensa-lx106-elf/include/libgen.h +++ b/libc/xtensa-lx106-elf/include/libgen.h @@ -6,13 +6,27 @@ #define _LIBGEN_H_ #include "_ansi.h" +#include #include #ifdef __cplusplus extern "C" { #endif -char *_EXFUN(basename, (char *)); +/* There are two common basename variants. If you do NOT #include + and you do + + #define _GNU_SOURCE + #include + + you get the GNU version. Otherwise you get the POSIX versionfor which you + should #include i for the function prototype. POSIX requires that + #undef basename will still let you invoke the underlying function. However, + this also implies that the POSIX version is used in this case. That's made + sure here. */ +#undef basename +#define basename __xpg_basename +char *_EXFUN(basename, (char *)) __asm__(__ASMNAME("basename")); char *_EXFUN(dirname, (char *)); #ifdef __cplusplus diff --git a/libc/xtensa-lx106-elf/include/limits.h b/libc/xtensa-lx106-elf/include/limits.h index 190f1f7..dd09c1c 100644 --- a/libc/xtensa-lx106-elf/include/limits.h +++ b/libc/xtensa-lx106-elf/include/limits.h @@ -2,6 +2,7 @@ # define _LIBC_LIMITS_H_ 1 #include +#include # ifdef _MB_LEN_MAX # define MB_LEN_MAX _MB_LEN_MAX @@ -96,8 +97,7 @@ # define __LONG_LONG_MAX__ 9223372036854775807LL # endif -# if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +# if __ISO_C_VISIBLE >= 1999 /* Minimum and maximum values a `signed long long int' can hold. */ # undef LLONG_MIN # define LLONG_MIN (-LLONG_MAX-1) @@ -109,7 +109,7 @@ # define ULLONG_MAX (LLONG_MAX * 2ULL + 1) # endif -# if defined (__GNU_LIBRARY__) ? defined (__USE_GNU) : !defined (__STRICT_ANSI__) +# if __GNU_VISIBLE /* Minimum and maximum values a `signed long long int' can hold. */ # undef LONG_LONG_MIN # define LONG_LONG_MIN (-LONG_LONG_MAX-1) diff --git a/libc/xtensa-lx106-elf/include/locale.h b/libc/xtensa-lx106-elf/include/locale.h index cbd658e..8ba88a9 100644 --- a/libc/xtensa-lx106-elf/include/locale.h +++ b/libc/xtensa-lx106-elf/include/locale.h @@ -8,6 +8,7 @@ #define _LOCALE_H_ #include "_ansi.h" +#include #define __need_NULL #include @@ -20,6 +21,22 @@ #define LC_TIME 5 #define LC_MESSAGES 6 +#if __POSIX_VISIBLE >= 200809 || defined (_COMPILING_NEWLIB) + +#include + +#define LC_ALL_MASK (1 << LC_ALL) +#define LC_COLLATE_MASK (1 << LC_COLLATE) +#define LC_CTYPE_MASK (1 << LC_CTYPE) +#define LC_MONETARY_MASK (1 << LC_MONETARY) +#define LC_NUMERIC_MASK (1 << LC_NUMERIC) +#define LC_TIME_MASK (1 << LC_TIME) +#define LC_MESSAGES_MASK (1 << LC_MESSAGES) + +#define LC_GLOBAL_LOCALE ((struct __locale_t *) -1) + +#endif /* __POSIX_VISIBLE >= 200809 */ + _BEGIN_STD_C struct lconv @@ -50,15 +67,30 @@ struct lconv char int_p_sign_posn; }; -#ifndef _REENT_ONLY -char *_EXFUN(setlocale,(int category, const char *locale)); -struct lconv *_EXFUN(localeconv,(void)); -#endif - struct _reent; -char *_EXFUN(_setlocale_r,(struct _reent *, int category, const char *locale)); +char *_EXFUN(_setlocale_r,(struct _reent *, int, const char *)); struct lconv *_EXFUN(_localeconv_r,(struct _reent *)); +struct __locale_t *_newlocale_r (struct _reent *, int, const char *, + struct __locale_t *); +void _freelocale_r (struct _reent *, struct __locale_t *); +struct __locale_t *_duplocale_r (struct _reent *, struct __locale_t *); +struct __locale_t *_uselocale_r (struct _reent *, struct __locale_t *); + +#ifndef _REENT_ONLY + +char *_EXFUN(setlocale,(int, const char *)); +struct lconv *_EXFUN(localeconv,(void)); + +#if __POSIX_VISIBLE >= 200809 +locale_t newlocale (int, const char *, locale_t); +void freelocale (locale_t); +locale_t duplocale (locale_t); +locale_t uselocale (locale_t); +#endif /* __POSIX_VISIBLE >= 200809 */ + +#endif /* _REENT_ONLY */ + _END_STD_C #endif /* _LOCALE_H_ */ diff --git a/libc/xtensa-lx106-elf/include/machine/_arc4random.h b/libc/xtensa-lx106-elf/include/machine/_arc4random.h new file mode 100644 index 0000000..52808d7 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/machine/_arc4random.h @@ -0,0 +1 @@ +/* Use default implementation, see arc4random.h */ diff --git a/libc/xtensa-lx106-elf/include/machine/_default_types.h b/libc/xtensa-lx106-elf/include/machine/_default_types.h index 03bdc52..59552f5 100644 --- a/libc/xtensa-lx106-elf/include/machine/_default_types.h +++ b/libc/xtensa-lx106-elf/include/machine/_default_types.h @@ -46,6 +46,9 @@ typedef __int64_t __int_least64_t; typedef __uint64_t __uint_least64_t; #define ___int_least64_t_defined +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + typedef __INTPTR_TYPE__ __intptr_t; typedef __UINTPTR_TYPE__ __uintptr_t; diff --git a/libc/xtensa-lx106-elf/include/machine/_endian.h b/libc/xtensa-lx106-elf/include/machine/_endian.h new file mode 100644 index 0000000..92a14dc --- /dev/null +++ b/libc/xtensa-lx106-elf/include/machine/_endian.h @@ -0,0 +1,35 @@ +#ifndef __MACHINE_ENDIAN_H__ +#error "must be included via " +#endif /* !__MACHINE_ENDIAN_H__ */ + +#include + +#ifdef __PPC__ +/* Get rid of GCC builtin defines on PowerPC */ +#ifdef _BIG_ENDIAN +#undef _BIG_ENDIAN +#endif +#ifdef _LITTLE_ENDIAN +#undef _LITTLE_ENDIAN +#endif +#endif /* __PPC__ */ + +#ifndef _LITTLE_ENDIAN +#define _LITTLE_ENDIAN 1234 +#endif + +#ifndef _BIG_ENDIAN +#define _BIG_ENDIAN 4321 +#endif + +#ifndef _PDP_ENDIAN +#define _PDP_ENDIAN 3412 +#endif + +#ifndef _BYTE_ORDER +#if defined(__IEEE_LITTLE_ENDIAN) || defined(__IEEE_BYTES_LITTLE_ENDIAN) +#define _BYTE_ORDER _LITTLE_ENDIAN +#else +#define _BYTE_ORDER _BIG_ENDIAN +#endif +#endif diff --git a/libc/xtensa-lx106-elf/include/machine/_time.h b/libc/xtensa-lx106-elf/include/machine/_time.h new file mode 100644 index 0000000..476760c --- /dev/null +++ b/libc/xtensa-lx106-elf/include/machine/_time.h @@ -0,0 +1,3 @@ +#ifndef _SYS_TIME_H_ +#error "must be included via " +#endif /* !_SYS_TIME_H_ */ diff --git a/libc/xtensa-lx106-elf/include/machine/endian.h b/libc/xtensa-lx106-elf/include/machine/endian.h index 07ebc8f..34a5726 100644 --- a/libc/xtensa-lx106-elf/include/machine/endian.h +++ b/libc/xtensa-lx106-elf/include/machine/endian.h @@ -1,20 +1,69 @@ #ifndef __MACHINE_ENDIAN_H__ +#define __MACHINE_ENDIAN_H__ -#include +#include +#include +#include -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif - -#ifndef BYTE_ORDER -#if defined(__IEEE_LITTLE_ENDIAN) || defined(__IEEE_BYTES_LITTLE_ENDIAN) -#define BYTE_ORDER LITTLE_ENDIAN +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 #else -#define BYTE_ORDER BIG_ENDIAN +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 #endif + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER #endif +#ifdef __GNUC__ +#define __bswap16(_x) __builtin_bswap16(_x) +#define __bswap32(_x) __builtin_bswap32(_x) +#define __bswap64(_x) __builtin_bswap64(_x) +#else /* __GNUC__ */ +static __inline __uint16_t +__bswap16(__uint16_t _x) +{ + + return ((__uint16_t)((_x >> 8) | ((_x << 8) & 0xff00))); +} + +static __inline __uint32_t +__bswap32(__uint32_t _x) +{ + + return ((__uint32_t)((_x >> 24) | ((_x >> 8) & 0xff00) | + ((_x << 8) & 0xff0000) | ((_x << 24) & 0xff000000))); +} + +static __inline __uint64_t +__bswap64(__uint64_t _x) +{ + + return ((__uint64_t)((_x >> 56) | ((_x >> 40) & 0xff00) | + ((_x >> 24) & 0xff0000) | ((_x >> 8) & 0xff000000) | + ((_x << 8) & ((__uint64_t)0xff << 32)) | + ((_x << 24) & ((__uint64_t)0xff << 40)) | + ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56)))); +} +#endif /* !__GNUC__ */ + +#ifndef __machine_host_to_from_network_defined +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define __htonl(_x) __bswap32(_x) +#define __htons(_x) __bswap16(_x) +#define __ntohl(_x) __bswap32(_x) +#define __ntohs(_x) __bswap16(_x) +#else +#define __htonl(_x) ((__uint32_t)(_x)) +#define __htons(_x) ((__uint16_t)(_x)) +#define __ntohl(_x) ((__uint32_t)(_x)) +#define __ntohs(_x) ((__uint16_t)(_x)) +#endif +#endif /* __machine_host_to_from_network_defined */ + #endif /* __MACHINE_ENDIAN_H__ */ diff --git a/libc/xtensa-lx106-elf/include/machine/ieeefp.h b/libc/xtensa-lx106-elf/include/machine/ieeefp.h index f11dc05..23c03a7 100644 --- a/libc/xtensa-lx106-elf/include/machine/ieeefp.h +++ b/libc/xtensa-lx106-elf/include/machine/ieeefp.h @@ -170,6 +170,10 @@ #define __IEEE_LITTLE_ENDIAN #endif +#ifdef __riscv +#define __IEEE_LITTLE_ENDIAN +#endif + #ifdef __i960__ #define __IEEE_LITTLE_ENDIAN #endif @@ -283,6 +287,10 @@ #define __IEEE_BIG_ENDIAN #endif +#ifdef __FT32__ +#define __IEEE_LITTLE_ENDIAN +#endif + #ifdef __mcore__ #define __IEEE_BIG_ENDIAN #endif @@ -415,6 +423,10 @@ # endif #endif +#ifdef __VISIUM__ +#define __IEEE_BIG_ENDIAN +#endif + #if (defined(__XTENSA__)) # ifdef __XTENSA_EB__ # define __IEEE_BIG_ENDIAN diff --git a/libc/xtensa-lx106-elf/include/machine/setjmp.h b/libc/xtensa-lx106-elf/include/machine/setjmp.h index 9f9d9e4..d93636b 100644 --- a/libc/xtensa-lx106-elf/include/machine/setjmp.h +++ b/libc/xtensa-lx106-elf/include/machine/setjmp.h @@ -92,6 +92,9 @@ _BEGIN_STD_C # define _JBLEN (13 * 4) # elif defined(__unix__) || defined(__rtems__) # define _JBLEN 9 +# elif defined(__iamcu__) +/* Intel MCU jmp_buf only covers callee-saved registers. */ +# define _JBLEN 6 # else # include "setjmp-dj.h" # endif @@ -250,6 +253,10 @@ _BEGIN_STD_C #define _JBLEN 10 #endif +#ifdef __FT32__ +#define _JBLEN 27 +#endif + #ifdef __iq2000__ #define _JBLEN 32 #endif @@ -258,6 +265,10 @@ _BEGIN_STD_C #define _JBLEN 16 #endif +#ifdef __arc__ +#define _JBLEN 25 /* r13-r30,blink,lp_count,lp_start,lp_end,mlo,mhi,status32 */ +#endif + #ifdef __MMIX__ /* Using a layout compatible with GCC's built-in. */ #define _JBLEN 5 @@ -314,6 +325,10 @@ _BEGIN_STD_C #define _JBLEN 18 #endif +#ifdef __ia64 +#define _JBLEN 64 +#endif + #ifdef __lm32__ #define _JBLEN 19 #endif @@ -365,6 +380,20 @@ _BEGIN_STD_C #define _JBLEN 0x44 #endif +#ifdef __VISIUM__ +/* All call-saved GP registers: r11-r19,r21,r22,r23. */ +#define _JBLEN 12 +#endif + +#ifdef __riscv +#define _JBTYPE long +#ifdef __riscv_32e +#define _JBLEN ((4*sizeof(long))/sizeof(long)) +#else +#define _JBLEN ((14*sizeof(long) + 12*sizeof(double))/sizeof(long)) +#endif +#endif + #ifdef _JBLEN #ifdef _JBTYPE typedef _JBTYPE jmp_buf[_JBLEN]; @@ -375,7 +404,7 @@ typedef int jmp_buf[_JBLEN]; _END_STD_C -#if defined(__CYGWIN__) || defined(__rtems__) +#if (defined(__CYGWIN__) || defined(__rtems__)) && __POSIX_VISIBLE #include #ifdef __cplusplus @@ -403,6 +432,13 @@ typedef int sigjmp_buf[_JBLEN+1+(sizeof (sigset_t)/sizeof (int))]; #define __SIGMASK_FUNC sigprocmask #endif +#ifdef __CYGWIN__ +/* Per POSIX, siglongjmp has to be implemented as function. Cygwin + provides functions for both, siglongjmp and sigsetjmp since 2.2.0. */ +extern void siglongjmp (sigjmp_buf, int) __attribute__ ((__noreturn__)); +extern int sigsetjmp (sigjmp_buf, int); +#endif + #if defined(__GNUC__) #define sigsetjmp(env, savemask) \ @@ -440,8 +476,8 @@ typedef int sigjmp_buf[_JBLEN+1+(sizeof (sigset_t)/sizeof (int))]; are equivalent to sigsetjmp/siglongjmp when not saving the signal mask. New applications should use sigsetjmp/siglongjmp instead. */ #ifdef __CYGWIN__ -extern void _longjmp(jmp_buf, int); -extern int _setjmp(jmp_buf); +extern void _longjmp (jmp_buf, int) __attribute__ ((__noreturn__)); +extern int _setjmp (jmp_buf); #else #define _setjmp(env) sigsetjmp ((env), 0) #define _longjmp(env, val) siglongjmp ((env), (val)) @@ -450,4 +486,4 @@ extern int _setjmp(jmp_buf); #ifdef __cplusplus } #endif -#endif /* __CYGWIN__ or __rtems__ */ +#endif /* (__CYGWIN__ or __rtems__) and __POSIX_VISIBLE */ diff --git a/libc/xtensa-lx106-elf/include/machine/time.h b/libc/xtensa-lx106-elf/include/machine/time.h index 06e2ccf..c75edaf 100644 --- a/libc/xtensa-lx106-elf/include/machine/time.h +++ b/libc/xtensa-lx106-elf/include/machine/time.h @@ -1,19 +1,15 @@ #ifndef _MACHTIME_H_ #define _MACHTIME_H_ -#if defined(__rtems__) -#define _CLOCKS_PER_SEC_ sysconf(_SC_CLK_TCK) -#else /* !__rtems__ */ -#if defined(__aarch64__) || defined(__arm__) || defined(__thumb__) +#if defined(__rtems__) || defined(__VISIUM__) || defined(__riscv) +#define _CLOCKS_PER_SEC_ 1000000 +#elif defined(__aarch64__) || defined(__arm__) || defined(__thumb__) #define _CLOCKS_PER_SEC_ 100 #endif -#endif /* !__rtems__ */ #ifdef __SPU__ -#include +#include int nanosleep (const struct timespec *, struct timespec *); #endif #endif /* _MACHTIME_H_ */ - - diff --git a/libc/xtensa-lx106-elf/include/machine/types.h b/libc/xtensa-lx106-elf/include/machine/types.h index 40a75fa..a5a64e6 100644 --- a/libc/xtensa-lx106-elf/include/machine/types.h +++ b/libc/xtensa-lx106-elf/include/machine/types.h @@ -1,30 +1,7 @@ -#ifndef _MACHTYPES_H_ -#define _MACHTYPES_H_ - /* - * The following section is RTEMS specific and is needed to more - * closely match the types defined in the BSD machine/types.h. - * This is needed to let the RTEMS/BSD TCP/IP stack compile. + * Newlib targets may provide an own version of this file in their machine + * directory to add custom user types for . */ -#if defined(__rtems__) -#include -#endif - -#define _CLOCK_T_ unsigned long /* clock() */ -#define _TIME_T_ long /* time() */ -#define _CLOCKID_T_ unsigned long -#define _TIMER_T_ unsigned long - -#ifndef _HAVE_SYSTYPES -typedef long int __off_t; -typedef int __pid_t; -#ifdef __GNUC__ -__extension__ typedef long long int __loff_t; -#else -typedef long int __loff_t; -#endif -#endif - -#endif /* _MACHTYPES_H_ */ - - +#ifndef _SYS_TYPES_H +#error "must be included via " +#endif /* !_SYS_TYPES_H */ diff --git a/libc/xtensa-lx106-elf/include/math.h b/libc/xtensa-lx106-elf/include/math.h index d16ce30..2a322ee 100644 --- a/libc/xtensa-lx106-elf/include/math.h +++ b/libc/xtensa-lx106-elf/include/math.h @@ -3,34 +3,12 @@ #define _MATH_H_ #include +#include #include #include "_ansi.h" _BEGIN_STD_C -/* __dmath, __fmath, and __ldmath are only here for backwards compatibility - * in case any code used them. They are no longer used by Newlib, itself, - * other than legacy. */ -union __dmath -{ - double d; - __ULong i[2]; -}; - -union __fmath -{ - float f; - __ULong i[1]; -}; - -#if defined(_HAVE_LONG_DOUBLE) -union __ldmath -{ - long double ld; - __ULong i[4]; -}; -#endif - /* Natural log of 2 */ #define _M_LN2 0.693147180559945309417 @@ -136,9 +114,26 @@ extern double fmod _PARAMS((double, double)); #endif /* ! defined (__math_68881) */ #endif /* ! defined (_REENT_ONLY) */ -#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#if __MISC_VISIBLE +extern int finite _PARAMS((double)); +extern int finitef _PARAMS((float)); +extern int finitel _PARAMS((long double)); +extern int isinff _PARAMS((float)); +extern int isnanf _PARAMS((float)); +#ifdef __CYGWIN__ /* not implemented in newlib yet */ +extern int isinfl _PARAMS((long double)); +extern int isnanl _PARAMS((long double)); +#endif +#if !defined(__cplusplus) || __cplusplus < 201103L +extern int isinf _PARAMS((double)); +#endif +#endif /* __MISC_VISIBLE */ +#if (__MISC_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 600)) \ + && (!defined(__cplusplus) || __cplusplus < 201103L) +extern int isnan _PARAMS((double)); +#endif +#if __ISO_C_VISIBLE >= 1999 /* ISO C99 types and macros. */ /* FIXME: FLT_EVAL_METHOD should somehow be gotten from float.h (which is hard, @@ -180,10 +175,10 @@ extern double fmod _PARAMS((double, double)); #define FP_NORMAL 4 #ifndef FP_ILOGB0 -# define FP_ILOGB0 (-INT_MAX) +# define FP_ILOGB0 (-__INT_MAX__) #endif #ifndef FP_ILOGBNAN -# define FP_ILOGBNAN INT_MAX +# define FP_ILOGBNAN __INT_MAX__ #endif #ifndef MATH_ERRNO @@ -205,35 +200,70 @@ extern int __fpclassifyd (double x); extern int __signbitf (float x); extern int __signbitd (double x); -#define fpclassify(__x) \ - ((sizeof(__x) == sizeof(float)) ? __fpclassifyf(__x) : \ - __fpclassifyd(__x)) - -#ifndef isfinite - #define isfinite(__y) \ - (__extension__ ({int __cy = fpclassify(__y); \ - __cy != FP_INFINITE && __cy != FP_NAN;})) -#endif - /* Note: isinf and isnan were once functions in newlib that took double * arguments. C99 specifies that these names are reserved for macros * supporting multiple floating point types. Thus, they are * now defined as macros. Implementations of the old functions * taking double arguments still exist for compatibility purposes - * (prototypes for them are in ). */ -#ifndef isinf - #define isinf(y) (fpclassify(y) == FP_INFINITE) + * (prototypes for them are earlier in this header). */ + +#if __GNUC_PREREQ (4, 4) + #define fpclassify(__x) (__builtin_fpclassify (FP_NAN, FP_INFINITE, \ + FP_NORMAL, FP_SUBNORMAL, \ + FP_ZERO, __x)) + #ifndef isfinite + #define isfinite(__x) (__builtin_isfinite (__x)) + #endif + #ifndef isinf + #define isinf(__x) (__builtin_isinf_sign (__x)) + #endif + #ifndef isnan + #define isnan(__x) (__builtin_isnan (__x)) + #endif + #define isnormal(__x) (__builtin_isnormal (__x)) +#else + #define fpclassify(__x) \ + ((sizeof(__x) == sizeof(float)) ? __fpclassifyf(__x) : \ + __fpclassifyd(__x)) + #ifndef isfinite + #define isfinite(__y) \ + (__extension__ ({int __cy = fpclassify(__y); \ + __cy != FP_INFINITE && __cy != FP_NAN;})) + #endif + #ifndef isinf + #define isinf(__x) (fpclassify(__x) == FP_INFINITE) + #endif + #ifndef isnan + #define isnan(__x) (fpclassify(__x) == FP_NAN) + #endif + #define isnormal(__x) (fpclassify(__x) == FP_NORMAL) #endif -#ifndef isnan - #define isnan(y) (fpclassify(y) == FP_NAN) +#if __GNUC_PREREQ (4, 0) + #if defined(_HAVE_LONG_DOUBLE) + #define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __builtin_signbitf(__x) : \ + (sizeof(__x) == sizeof(double)) ? __builtin_signbit (__x) : \ + __builtin_signbitl(__x)) + #else + #define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __builtin_signbitf(__x) : \ + __builtin_signbit (__x)) + #endif +#else + #define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : \ + __signbitd(__x)) #endif -#define isnormal(y) (fpclassify(y) == FP_NORMAL) -#define signbit(__x) \ - ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : \ - __signbitd(__x)) - +#if __GNUC_PREREQ (2, 97) +#define isgreater(__x,__y) (__builtin_isgreater (__x, __y)) +#define isgreaterequal(__x,__y) (__builtin_isgreaterequal (__x, __y)) +#define isless(__x,__y) (__builtin_isless (__x, __y)) +#define islessequal(__x,__y) (__builtin_islessequal (__x, __y)) +#define islessgreater(__x,__y) (__builtin_islessgreater (__x, __y)) +#define isunordered(__x,__y) (__builtin_isunordered (__x, __y)) +#else #define isgreater(x,y) \ (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \ !isunordered(__x,__y) && (__x > __y);})) @@ -253,12 +283,12 @@ extern int __signbitd (double x); #define isunordered(a,b) \ (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \ fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;})) +#endif /* Non ANSI double precision functions. */ extern double infinity _PARAMS((void)); extern double nan _PARAMS((const char *)); -extern int finite _PARAMS((double)); extern double copysign _PARAMS((double, double)); extern double logb _PARAMS((double)); extern int ilogb _PARAMS((double)); @@ -357,7 +387,6 @@ extern float fmaf _PARAMS((float, float, float)); extern float infinityf _PARAMS((void)); extern float nanf _PARAMS((const char *)); -extern int finitef _PARAMS((float)); extern float copysignf _PARAMS((float, float)); extern float logbf _PARAMS((float)); extern int ilogbf _PARAMS((float)); @@ -382,8 +411,12 @@ extern float log2f _PARAMS((float)); extern float hypotf _PARAMS((float, float)); #endif /* ! defined (_REENT_ONLY) */ -/* On platforms where long double equals double. */ -#ifdef _LDBL_EQ_DBL +/* Newlib doesn't fully support long double math functions so far. + On platforms where long double equals double the long double functions + simply call the double functions. On Cygwin the long double functions + are implemented independently from newlib to be able to use optimized + assembler functions despite using the Microsoft x86_64 ABI. */ +#if defined (_LDBL_EQ_DBL) || defined (__CYGWIN__) /* Reentrant ANSI C functions. */ #ifndef __math_68881 extern long double atanl _PARAMS((long double)); @@ -453,44 +486,56 @@ extern long double lgammal _PARAMS((long double)); extern long double erfl _PARAMS((long double)); extern long double erfcl _PARAMS((long double)); #endif /* ! defined (_REENT_ONLY) */ -#else /* !_LDBL_EQ_DBL */ +#else /* !_LDBL_EQ_DBL && !__CYGWIN__ */ +extern long double hypotl _PARAMS((long double, long double)); +extern long double sqrtl _PARAMS((long double)); #ifdef __i386__ /* Other long double precision functions. */ extern _LONG_DOUBLE rintl _PARAMS((_LONG_DOUBLE)); extern long int lrintl _PARAMS((_LONG_DOUBLE)); extern long long int llrintl _PARAMS((_LONG_DOUBLE)); #endif /* __i386__ */ -#endif /* !_LDBL_EQ_DBL */ +#endif /* !_LDBL_EQ_DBL && !__CYGWIN__ */ -#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) */ - -#if !defined (__STRICT_ANSI__) || defined(__cplusplus) +#endif /* __ISO_C_VISIBLE >= 1999 */ +#if __MISC_VISIBLE extern double drem _PARAMS((double, double)); -extern void sincos _PARAMS((double, double *, double *)); +extern float dremf _PARAMS((float, float)); +#ifdef __CYGWIN__ +extern float dreml _PARAMS((long double, long double)); +#endif /* __CYGWIN__ */ extern double gamma_r _PARAMS((double, int *)); extern double lgamma_r _PARAMS((double, int *)); +extern float gammaf_r _PARAMS((float, int *)); +extern float lgammaf_r _PARAMS((float, int *)); +#endif +#if __MISC_VISIBLE || __XSI_VISIBLE extern double y0 _PARAMS((double)); extern double y1 _PARAMS((double)); extern double yn _PARAMS((int, double)); extern double j0 _PARAMS((double)); extern double j1 _PARAMS((double)); extern double jn _PARAMS((int, double)); +#endif -extern float dremf _PARAMS((float, float)); -extern void sincosf _PARAMS((float, float *, float *)); -extern float gammaf_r _PARAMS((float, int *)); -extern float lgammaf_r _PARAMS((float, int *)); - +#if __MISC_VISIBLE || __XSI_VISIBLE >= 600 extern float y0f _PARAMS((float)); extern float y1f _PARAMS((float)); extern float ynf _PARAMS((int, float)); extern float j0f _PARAMS((float)); extern float j1f _PARAMS((float)); extern float jnf _PARAMS((int, float)); +#endif /* GNU extensions */ +#if __GNU_VISIBLE +extern void sincos _PARAMS((double, double *, double *)); +extern void sincosf _PARAMS((float, float *, float *)); +#ifdef __CYGWIN__ +extern void sincosl _PARAMS((long double, long double *, long double *)); +#endif /* __CYGWIN__ */ # ifndef exp10 extern double exp10 _PARAMS((double)); # endif @@ -503,11 +548,17 @@ extern float exp10f _PARAMS((float)); # ifndef pow10f extern float pow10f _PARAMS((float)); # endif +#ifdef __CYGWIN__ +# ifndef exp10l +extern float exp10l _PARAMS((float)); +# endif +# ifndef pow10l +extern float pow10l _PARAMS((float)); +# endif +#endif /* __CYGWIN__ */ +#endif /* __GNU_VISIBLE */ -#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) */ - -#ifndef __STRICT_ANSI__ - +#if __MISC_VISIBLE || __XSI_VISIBLE /* The gamma functions use a global variable, signgam. */ #ifndef _REENT_ONLY #define signgam (*__signgam()) @@ -515,7 +566,9 @@ extern int *__signgam _PARAMS((void)); #endif /* ! defined (_REENT_ONLY) */ #define __signgam_r(ptr) _REENT_SIGNGAM(ptr) +#endif /* __MISC_VISIBLE || __XSI_VISIBLE */ +#if __SVID_VISIBLE /* The exception structure passed to the matherr routine. */ /* We have a problem when using C++ since `exception' is a reserved name in C++. */ @@ -548,11 +601,11 @@ extern int matherr _PARAMS((struct exception *e)); #define TLOSS 5 #define PLOSS 6 -#endif /* ! defined (__STRICT_ANSI__) */ +#endif /* __SVID_VISIBLE */ /* Useful constants. */ -#if !defined(__STRICT_ANSI__) || ((_XOPEN_SOURCE - 0) >= 500) +#if __BSD_VISIBLE || __XSI_VISIBLE #define MAXFLOAT 3.40282347e+38F @@ -572,7 +625,7 @@ extern int matherr _PARAMS((struct exception *e)); #endif -#ifndef __STRICT_ANSI__ +#if __BSD_VISIBLE #define M_TWOPI (M_PI * 2.0) #define M_3PI_4 2.3561944901923448370E0 @@ -604,7 +657,7 @@ extern __IMPORT _LIB_VERSION_TYPE _LIB_VERSION; #define _XOPEN_ __fdlibm_xopen #define _POSIX_ __fdlibm_posix -#endif /* ! defined (__STRICT_ANSI__) */ +#endif /* __BSD_VISIBLE */ _END_STD_C diff --git a/libc/xtensa-lx106-elf/include/memory.h b/libc/xtensa-lx106-elf/include/memory.h new file mode 100644 index 0000000..f4a14fc --- /dev/null +++ b/libc/xtensa-lx106-elf/include/memory.h @@ -0,0 +1,4 @@ +#ifndef _MEMORY_H +#define _MEMORY_H +#include +#endif /* !_MEMORY_H */ diff --git a/libc/xtensa-lx106-elf/include/newlib.h b/libc/xtensa-lx106-elf/include/newlib.h index e9bf566..f4dd838 100644 --- a/libc/xtensa-lx106-elf/include/newlib.h +++ b/libc/xtensa-lx106-elf/include/newlib.h @@ -11,7 +11,7 @@ /* #undef _ELIX_LEVEL */ /* Newlib version */ -#define _NEWLIB_VERSION "2.2.0" +#include <_newlib_version.h> /* C99 formats support (such as %a, %zu, ...) in IO functions like * printf/scanf enabled */ @@ -62,12 +62,6 @@ /* True if long double supported and it is equal to double. */ #define _LDBL_EQ_DBL 1 -/* Define if uintptr_t is unsigned long on this architecture */ -/* #undef _UINTPTR_EQ_ULONG */ - -/* Define if uintptr_t is unsigned long long on this architecture */ -/* #undef _UINTPTR_EQ_ULONGLONG */ - /* Define if ivo supported in streamio. */ #define _FVWRITE_IN_STREAMIO 1 @@ -86,9 +80,20 @@ /* Define if declare atexit data as global. */ /* #undef _REENT_GLOBAL_ATEXIT */ +/* Define to move the stdio stream FILE objects out of struct _reent and make + them global. The stdio stream pointers of struct _reent are initialized to + point to the global stdio FILE stream objects. */ +/* #undef _WANT_REENT_GLOBAL_STDIO_STREAMS */ + /* Define if small footprint nano-formatted-IO implementation used. */ #define _NANO_FORMATTED_IO 1 +/* Define if using retargetable functions for default lock routines. */ +/* #undef _RETARGETABLE_LOCKING */ + +/* Define to use type long for time_t. */ +/* #undef _WANT_USE_LONG_TIME_T */ + /* * Iconv encodings enabled ("to" direction) */ diff --git a/libc/xtensa-lx106-elf/include/pthread.h b/libc/xtensa-lx106-elf/include/pthread.h index db1f9c1..516131d 100644 --- a/libc/xtensa-lx106-elf/include/pthread.h +++ b/libc/xtensa-lx106-elf/include/pthread.h @@ -1,8 +1,7 @@ -/* pthread.h +/* + * Written by Joel Sherrill . * - * Written by Joel Sherrill . - * - * COPYRIGHT (c) 1989-2013. + * COPYRIGHT (c) 1989-2013, 2015. * On-Line Applications Research Corporation (OAR). * * Permission to use, copy, modify, and distribute this software for any @@ -14,8 +13,6 @@ * WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - * $Id$ */ #ifndef __PTHREAD_h @@ -31,7 +28,7 @@ extern "C" { #include #include -#include +#include #include struct _pthread_cleanup_context { @@ -76,7 +73,7 @@ int _EXFUN(pthread_mutex_destroy, (pthread_mutex_t *__mutex)); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */ -#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF) +#define PTHREAD_MUTEX_INITIALIZER _PTHREAD_MUTEX_INITIALIZER /* Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93 NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29 */ @@ -96,6 +93,13 @@ int _EXFUN(pthread_mutex_timedlock, int _EXFUN(pthread_condattr_init, (pthread_condattr_t *__attr)); int _EXFUN(pthread_condattr_destroy, (pthread_condattr_t *__attr)); + +int _EXFUN(pthread_condattr_getclock, + (const pthread_condattr_t *__restrict __attr, + clockid_t *__restrict __clock_id)); +int _EXFUN(pthread_condattr_setclock, + (pthread_condattr_t *__attr, clockid_t __clock_id)); + int _EXFUN(pthread_condattr_getpshared, (_CONST pthread_condattr_t *__attr, int *__pshared)); int _EXFUN(pthread_condattr_setpshared, @@ -112,7 +116,7 @@ int _EXFUN(pthread_cond_destroy, (pthread_cond_t *__mutex)); pthread_cond_t cond = PTHREAD_COND_INITIALIZER; */ -#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) 0xFFFFFFFF) +#define PTHREAD_COND_INITIALIZER _PTHREAD_COND_INITIALIZER /* Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101 */ @@ -161,8 +165,17 @@ int _EXFUN(pthread_getschedparam, int _EXFUN(pthread_setschedparam, (pthread_t __pthread, int __policy, struct sched_param *__param)); +/* Set Scheduling Priority of a Thread */ +int _EXFUN(pthread_setschedprio, (pthread_t thread, int prio)); + #endif /* defined(_POSIX_THREAD_PRIORITY_SCHEDULING) */ +#if __GNU_VISIBLE +int pthread_getname_np(pthread_t, char *, size_t) __nonnull(2); + +int pthread_setname_np(pthread_t, const char *) __nonnull(2); +#endif + #if defined(_POSIX_THREAD_PRIO_INHERIT) || defined(_POSIX_THREAD_PRIO_PROTECT) /* Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128 */ @@ -218,7 +231,7 @@ int _EXFUN(pthread_attr_setguardsize, * in GNU/Linux. They may be provided by other OSes for * compatibility. */ -#if defined(__GNU_VISIBLE) +#if __GNU_VISIBLE #if defined(__rtems__) int _EXFUN(pthread_attr_setaffinity_np, (pthread_attr_t *__attr, size_t __cpusetsize, @@ -235,7 +248,7 @@ int _EXFUN(pthread_getaffinity_np, int _EXFUN(pthread_getattr_np, (pthread_t __id, pthread_attr_t *__attr)); #endif /* defined(__rtems__) */ -#endif /* defined(__GNU_VISIBLE) */ +#endif /* __GNU_VISIBLE */ /* Thread Creation, P1003.1c/Draft 10, p. 144 */ @@ -253,7 +266,7 @@ int _EXFUN(pthread_detach, (pthread_t __pthread)); /* Thread Termination, p1003.1c/Draft 10, p. 150 */ -void _EXFUN(pthread_exit, (void *__value_ptr)); +void _EXFUN(pthread_exit, (void *__value_ptr)) __dead2; /* Get Calling Thread's ID, p1003.1c/Draft 10, p. XXX */ @@ -263,6 +276,18 @@ pthread_t _EXFUN(pthread_self, (void)); int _EXFUN(pthread_equal, (pthread_t __t1, pthread_t __t2)); +/* Retrieve ID of a Thread's CPU Time Clock */ +int _EXFUN(pthread_getcpuclockid, + (pthread_t thread, clockid_t *clock_id)); + +/* Get/Set Current Thread's Concurrency Level */ +int _EXFUN(pthread_setconcurrency, (int new_level)); +int _EXFUN(pthread_getconcurrency, (void)); + +#if __BSD_VISIBLE || __GNU_VISIBLE +void _EXFUN(pthread_yield, (void)); +#endif + /* Dynamic Package Initialization */ /* This is used to statically initialize a pthread_once_t. Example: @@ -271,7 +296,7 @@ int _EXFUN(pthread_equal, (pthread_t __t1, pthread_t __t2)); NOTE: This is named inconsistently -- it should be INITIALIZER. */ -#define PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */ +#define PTHREAD_ONCE_INIT _PTHREAD_ONCE_INIT int _EXFUN(pthread_once, (pthread_once_t *__once_control, void (*__init_routine)(void))); @@ -329,7 +354,7 @@ void _EXFUN(_pthread_cleanup_pop, _pthread_cleanup_pop(&_pthread_clup_ctx, (_execute)); \ } while (0) -#if defined(_GNU_SOURCE) +#if __GNU_VISIBLE void _EXFUN(_pthread_cleanup_push_defer, (struct _pthread_cleanup_context *_context, void (*_routine)(void *), void *_arg)); @@ -347,7 +372,7 @@ void _EXFUN(_pthread_cleanup_pop_restore, #define pthread_cleanup_pop_restore_np(_execute) \ _pthread_cleanup_pop_restore(&_pthread_clup_ctx, (_execute)); \ } while (0) -#endif /* defined(_GNU_SOURCE) */ +#endif /* __GNU_VISIBLE */ #if defined(_POSIX_THREAD_CPUTIME) @@ -398,7 +423,7 @@ int _EXFUN(pthread_spin_unlock, (pthread_spinlock_t *__spinlock)); pthread_mutex_t mutex = PTHREAD_RWLOCK_INITIALIZER; */ -#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) 0xFFFFFFFF) +#define PTHREAD_RWLOCK_INITIALIZER _PTHREAD_RWLOCK_INITIALIZER int _EXFUN(pthread_rwlockattr_init, (pthread_rwlockattr_t *__attr)); int _EXFUN(pthread_rwlockattr_destroy, (pthread_rwlockattr_t *__attr)); diff --git a/libc/xtensa-lx106-elf/include/pwd.h b/libc/xtensa-lx106-elf/include/pwd.h index 3dea4ee..f37d289 100644 --- a/libc/xtensa-lx106-elf/include/pwd.h +++ b/libc/xtensa-lx106-elf/include/pwd.h @@ -63,14 +63,14 @@ struct passwd { struct passwd *getpwuid (uid_t); struct passwd *getpwnam (const char *); -#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 +#if __MISC_VISIBLE || __POSIX_VISIBLE int getpwnam_r (const char *, struct passwd *, char *, size_t , struct passwd **); int getpwuid_r (uid_t, struct passwd *, char *, size_t, struct passwd **); #endif -#if __XSI_VISIBLE >= 500 +#if __MISC_VISIBLE || __XSI_VISIBLE >= 4 struct passwd *getpwent (void); void setpwent (void); void endpwent (void); diff --git a/libc/xtensa-lx106-elf/include/reent.h b/libc/xtensa-lx106-elf/include/reent.h index 861be71..b7664b0 100644 --- a/libc/xtensa-lx106-elf/include/reent.h +++ b/libc/xtensa-lx106-elf/include/reent.h @@ -92,7 +92,6 @@ extern "C" { #include #include -#include #define __need_size_t #define __need_ptrdiff_t diff --git a/libc/xtensa-lx106-elf/include/signal.h b/libc/xtensa-lx106-elf/include/signal.h index 8c50a2e..0324ae7 100644 --- a/libc/xtensa-lx106-elf/include/signal.h +++ b/libc/xtensa-lx106-elf/include/signal.h @@ -2,15 +2,18 @@ #define _SIGNAL_H_ #include "_ansi.h" +#include #include _BEGIN_STD_C typedef int sig_atomic_t; /* Atomic entity type (ANSI) */ -#ifndef _POSIX_SOURCE +#if __BSD_VISIBLE typedef _sig_func_ptr sig_t; /* BSD naming */ +#endif +#if __GNU_VISIBLE typedef _sig_func_ptr sighandler_t; /* glibc naming */ -#endif /* !_POSIX_SOURCE */ +#endif #define SIG_DFL ((_sig_func_ptr)0) /* Default action */ #define SIG_IGN ((_sig_func_ptr)1) /* Ignore action */ diff --git a/libc/xtensa-lx106-elf/include/stdint.h b/libc/xtensa-lx106-elf/include/stdint.h index 7386164..4abdacb 100644 --- a/libc/xtensa-lx106-elf/include/stdint.h +++ b/libc/xtensa-lx106-elf/include/stdint.h @@ -11,53 +11,30 @@ #include #include +#include #ifdef __cplusplus extern "C" { #endif -#ifdef ___int8_t_defined -typedef __int8_t int8_t ; -typedef __uint8_t uint8_t ; -#define __int8_t_defined 1 -#endif - #ifdef ___int_least8_t_defined typedef __int_least8_t int_least8_t; typedef __uint_least8_t uint_least8_t; #define __int_least8_t_defined 1 #endif -#ifdef ___int16_t_defined -typedef __int16_t int16_t ; -typedef __uint16_t uint16_t ; -#define __int16_t_defined 1 -#endif - #ifdef ___int_least16_t_defined typedef __int_least16_t int_least16_t; typedef __uint_least16_t uint_least16_t; #define __int_least16_t_defined 1 #endif -#ifdef ___int32_t_defined -typedef __int32_t int32_t ; -typedef __uint32_t uint32_t ; -#define __int32_t_defined 1 -#endif - #ifdef ___int_least32_t_defined typedef __int_least32_t int_least32_t; typedef __uint_least32_t uint_least32_t; #define __int_least32_t_defined 1 #endif -#ifdef ___int64_t_defined -typedef __int64_t int64_t ; -typedef __uint64_t uint64_t ; -#define __int64_t_defined 1 -#endif - #ifdef ___int_least64_t_defined typedef __int_least64_t int_least64_t; typedef __uint_least64_t uint_least64_t; @@ -147,37 +124,15 @@ typedef __uint_least64_t uint_least64_t; #endif #endif -/* Greatest-width integer types */ -/* Modern GCCs provide __INTMAX_TYPE__ */ -#if defined(__INTMAX_TYPE__) - typedef __INTMAX_TYPE__ intmax_t; -#elif __have_longlong64 - typedef signed long long intmax_t; -#else - typedef signed long intmax_t; -#endif - -/* Modern GCCs provide __UINTMAX_TYPE__ */ -#if defined(__UINTMAX_TYPE__) - typedef __UINTMAX_TYPE__ uintmax_t; -#elif __have_longlong64 - typedef unsigned long long uintmax_t; -#else - typedef unsigned long uintmax_t; -#endif - -typedef __intptr_t intptr_t; -typedef __uintptr_t uintptr_t; - #ifdef __INTPTR_TYPE__ #define INTPTR_MIN (-__INTPTR_MAX__ - 1) -#define INTPTR_MAX __INTPTR_MAX__ -#define UINTPTR_MAX __UINTPTR_MAX__ +#define INTPTR_MAX (__INTPTR_MAX__) +#define UINTPTR_MAX (__UINTPTR_MAX__) #elif defined(__PTRDIFF_TYPE__) #define INTPTR_MAX PTRDIFF_MAX #define INTPTR_MIN PTRDIFF_MIN #ifdef __UINTPTR_MAX__ -#define UINTPTR_MAX __UINTPTR_MAX__ +#define UINTPTR_MAX (__UINTPTR_MAX__) #else #define UINTPTR_MAX (2UL * PTRDIFF_MAX + 1) #endif @@ -186,7 +141,7 @@ typedef __uintptr_t uintptr_t; * Fallback to hardcoded values, * should be valid on cpu's with 32bit int/32bit void* */ -#define INTPTR_MAX __STDINT_EXP(LONG_MAX) +#define INTPTR_MAX (__STDINT_EXP(LONG_MAX)) #define INTPTR_MIN (-__STDINT_EXP(LONG_MAX) - 1) #define UINTPTR_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1) #endif @@ -195,77 +150,77 @@ typedef __uintptr_t uintptr_t; #ifdef __INT8_MAX__ #define INT8_MIN (-__INT8_MAX__ - 1) -#define INT8_MAX __INT8_MAX__ -#define UINT8_MAX __UINT8_MAX__ +#define INT8_MAX (__INT8_MAX__) +#define UINT8_MAX (__UINT8_MAX__) #elif defined(__int8_t_defined) -#define INT8_MIN -128 -#define INT8_MAX 127 -#define UINT8_MAX 255 +#define INT8_MIN (-128) +#define INT8_MAX (127) +#define UINT8_MAX (255) #endif #ifdef __INT_LEAST8_MAX__ #define INT_LEAST8_MIN (-__INT_LEAST8_MAX__ - 1) -#define INT_LEAST8_MAX __INT_LEAST8_MAX__ -#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__ +#define INT_LEAST8_MAX (__INT_LEAST8_MAX__) +#define UINT_LEAST8_MAX (__UINT_LEAST8_MAX__) #elif defined(__int_least8_t_defined) -#define INT_LEAST8_MIN -128 -#define INT_LEAST8_MAX 127 -#define UINT_LEAST8_MAX 255 +#define INT_LEAST8_MIN (-128) +#define INT_LEAST8_MAX (127) +#define UINT_LEAST8_MAX (255) #else #error required type int_least8_t missing #endif #ifdef __INT16_MAX__ #define INT16_MIN (-__INT16_MAX__ - 1) -#define INT16_MAX __INT16_MAX__ -#define UINT16_MAX __UINT16_MAX__ +#define INT16_MAX (__INT16_MAX__) +#define UINT16_MAX (__UINT16_MAX__) #elif defined(__int16_t_defined) -#define INT16_MIN -32768 -#define INT16_MAX 32767 -#define UINT16_MAX 65535 +#define INT16_MIN (-32768) +#define INT16_MAX (32767) +#define UINT16_MAX (65535) #endif #ifdef __INT_LEAST16_MAX__ #define INT_LEAST16_MIN (-__INT_LEAST16_MAX__ - 1) -#define INT_LEAST16_MAX __INT_LEAST16_MAX__ -#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__ +#define INT_LEAST16_MAX (__INT_LEAST16_MAX__) +#define UINT_LEAST16_MAX (__UINT_LEAST16_MAX__) #elif defined(__int_least16_t_defined) -#define INT_LEAST16_MIN -32768 -#define INT_LEAST16_MAX 32767 -#define UINT_LEAST16_MAX 65535 +#define INT_LEAST16_MIN (-32768) +#define INT_LEAST16_MAX (32767) +#define UINT_LEAST16_MAX (65535) #else #error required type int_least16_t missing #endif #ifdef __INT32_MAX__ #define INT32_MIN (-__INT32_MAX__ - 1) -#define INT32_MAX __INT32_MAX__ -#define UINT32_MAX __UINT32_MAX__ +#define INT32_MAX (__INT32_MAX__) +#define UINT32_MAX (__UINT32_MAX__) #elif defined(__int32_t_defined) -#if __have_long32 +#if defined (_INT32_EQ_LONG) #define INT32_MIN (-2147483647L-1) -#define INT32_MAX 2147483647L -#define UINT32_MAX 4294967295UL +#define INT32_MAX (2147483647L) +#define UINT32_MAX (4294967295UL) #else #define INT32_MIN (-2147483647-1) -#define INT32_MAX 2147483647 -#define UINT32_MAX 4294967295U +#define INT32_MAX (2147483647) +#define UINT32_MAX (4294967295U) #endif #endif #ifdef __INT_LEAST32_MAX__ #define INT_LEAST32_MIN (-__INT_LEAST32_MAX__ - 1) -#define INT_LEAST32_MAX __INT_LEAST32_MAX__ -#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__ +#define INT_LEAST32_MAX (__INT_LEAST32_MAX__) +#define UINT_LEAST32_MAX (__UINT_LEAST32_MAX__) #elif defined(__int_least32_t_defined) -#if __have_long32 +#if defined (_INT32_EQ_LONG) #define INT_LEAST32_MIN (-2147483647L-1) -#define INT_LEAST32_MAX 2147483647L -#define UINT_LEAST32_MAX 4294967295UL +#define INT_LEAST32_MAX (2147483647L) +#define UINT_LEAST32_MAX (4294967295UL) #else #define INT_LEAST32_MIN (-2147483647-1) -#define INT_LEAST32_MAX 2147483647 -#define UINT_LEAST32_MAX 4294967295U +#define INT_LEAST32_MAX (2147483647) +#define UINT_LEAST32_MAX (4294967295U) #endif #else #error required type int_least32_t missing @@ -273,44 +228,44 @@ typedef __uintptr_t uintptr_t; #ifdef __INT64_MAX__ #define INT64_MIN (-__INT64_MAX__ - 1) -#define INT64_MAX __INT64_MAX__ -#define UINT64_MAX __UINT64_MAX__ +#define INT64_MAX (__INT64_MAX__) +#define UINT64_MAX (__UINT64_MAX__) #elif defined(__int64_t_defined) #if __have_long64 #define INT64_MIN (-9223372036854775807L-1L) -#define INT64_MAX 9223372036854775807L -#define UINT64_MAX 18446744073709551615U +#define INT64_MAX (9223372036854775807L) +#define UINT64_MAX (18446744073709551615U) #elif __have_longlong64 #define INT64_MIN (-9223372036854775807LL-1LL) -#define INT64_MAX 9223372036854775807LL -#define UINT64_MAX 18446744073709551615ULL +#define INT64_MAX (9223372036854775807LL) +#define UINT64_MAX (18446744073709551615ULL) #endif #endif #ifdef __INT_LEAST64_MAX__ #define INT_LEAST64_MIN (-__INT_LEAST64_MAX__ - 1) -#define INT_LEAST64_MAX __INT_LEAST64_MAX__ -#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__ +#define INT_LEAST64_MAX (__INT_LEAST64_MAX__) +#define UINT_LEAST64_MAX (__UINT_LEAST64_MAX__) #elif defined(__int_least64_t_defined) #if __have_long64 #define INT_LEAST64_MIN (-9223372036854775807L-1L) -#define INT_LEAST64_MAX 9223372036854775807L -#define UINT_LEAST64_MAX 18446744073709551615U +#define INT_LEAST64_MAX (9223372036854775807L) +#define UINT_LEAST64_MAX (18446744073709551615U) #elif __have_longlong64 #define INT_LEAST64_MIN (-9223372036854775807LL-1LL) -#define INT_LEAST64_MAX 9223372036854775807LL -#define UINT_LEAST64_MAX 18446744073709551615ULL +#define INT_LEAST64_MAX (9223372036854775807LL) +#define UINT_LEAST64_MAX (18446744073709551615ULL) #endif #endif #ifdef __INT_FAST8_MAX__ #define INT_FAST8_MIN (-__INT_FAST8_MAX__ - 1) -#define INT_FAST8_MAX __INT_FAST8_MAX__ -#define UINT_FAST8_MAX __UINT_FAST8_MAX__ +#define INT_FAST8_MAX (__INT_FAST8_MAX__) +#define UINT_FAST8_MAX (__UINT_FAST8_MAX__) #elif defined(__int_fast8_t_defined) #if __STDINT_EXP(INT_MAX) >= 0x7f #define INT_FAST8_MIN (-__STDINT_EXP(INT_MAX)-1) -#define INT_FAST8_MAX __STDINT_EXP(INT_MAX) +#define INT_FAST8_MAX (__STDINT_EXP(INT_MAX)) #define UINT_FAST8_MAX (__STDINT_EXP(INT_MAX)*2U+1U) #else #define INT_FAST8_MIN INT_LEAST8_MIN @@ -321,12 +276,12 @@ typedef __uintptr_t uintptr_t; #ifdef __INT_FAST16_MAX__ #define INT_FAST16_MIN (-__INT_FAST16_MAX__ - 1) -#define INT_FAST16_MAX __INT_FAST16_MAX__ -#define UINT_FAST16_MAX __UINT_FAST16_MAX__ +#define INT_FAST16_MAX (__INT_FAST16_MAX__) +#define UINT_FAST16_MAX (__UINT_FAST16_MAX__) #elif defined(__int_fast16_t_defined) #if __STDINT_EXP(INT_MAX) >= 0x7fff #define INT_FAST16_MIN (-__STDINT_EXP(INT_MAX)-1) -#define INT_FAST16_MAX __STDINT_EXP(INT_MAX) +#define INT_FAST16_MAX (__STDINT_EXP(INT_MAX)) #define UINT_FAST16_MAX (__STDINT_EXP(INT_MAX)*2U+1U) #else #define INT_FAST16_MIN INT_LEAST16_MIN @@ -337,12 +292,12 @@ typedef __uintptr_t uintptr_t; #ifdef __INT_FAST32_MAX__ #define INT_FAST32_MIN (-__INT_FAST32_MAX__ - 1) -#define INT_FAST32_MAX __INT_FAST32_MAX__ -#define UINT_FAST32_MAX __UINT_FAST32_MAX__ +#define INT_FAST32_MAX (__INT_FAST32_MAX__) +#define UINT_FAST32_MAX (__UINT_FAST32_MAX__) #elif defined(__int_fast32_t_defined) #if __STDINT_EXP(INT_MAX) >= 0x7fffffff #define INT_FAST32_MIN (-__STDINT_EXP(INT_MAX)-1) -#define INT_FAST32_MAX __STDINT_EXP(INT_MAX) +#define INT_FAST32_MAX (__STDINT_EXP(INT_MAX)) #define UINT_FAST32_MAX (__STDINT_EXP(INT_MAX)*2U+1U) #else #define INT_FAST32_MIN INT_LEAST32_MIN @@ -353,12 +308,12 @@ typedef __uintptr_t uintptr_t; #ifdef __INT_FAST64_MAX__ #define INT_FAST64_MIN (-__INT_FAST64_MAX__ - 1) -#define INT_FAST64_MAX __INT_FAST64_MAX__ -#define UINT_FAST64_MAX __UINT_FAST64_MAX__ +#define INT_FAST64_MAX (__INT_FAST64_MAX__) +#define UINT_FAST64_MAX (__UINT_FAST64_MAX__) #elif defined(__int_fast64_t_defined) #if __STDINT_EXP(INT_MAX) > 0x7fffffff #define INT_FAST64_MIN (-__STDINT_EXP(INT_MAX)-1) -#define INT_FAST64_MAX __STDINT_EXP(INT_MAX) +#define INT_FAST64_MAX (__STDINT_EXP(INT_MAX)) #define UINT_FAST64_MAX (__STDINT_EXP(INT_MAX)*2U+1U) #else #define INT_FAST64_MIN INT_LEAST64_MIN @@ -368,7 +323,7 @@ typedef __uintptr_t uintptr_t; #endif #ifdef __INTMAX_MAX__ -#define INTMAX_MAX __INTMAX_MAX__ +#define INTMAX_MAX (__INTMAX_MAX__) #define INTMAX_MIN (-INTMAX_MAX - 1) #elif defined(__INTMAX_TYPE__) /* All relevant GCC versions prefer long to long long for intmax_t. */ @@ -377,7 +332,7 @@ typedef __uintptr_t uintptr_t; #endif #ifdef __UINTMAX_MAX__ -#define UINTMAX_MAX __UINTMAX_MAX__ +#define UINTMAX_MAX (__UINTMAX_MAX__) #elif defined(__UINTMAX_TYPE__) /* All relevant GCC versions prefer long to long long for intmax_t. */ #define UINTMAX_MAX UINT64_MAX @@ -385,27 +340,27 @@ typedef __uintptr_t uintptr_t; /* This must match size_t in stddef.h, currently long unsigned int */ #ifdef __SIZE_MAX__ -#define SIZE_MAX __SIZE_MAX__ +#define SIZE_MAX (__SIZE_MAX__) #else #define SIZE_MAX (__STDINT_EXP(LONG_MAX) * 2UL + 1) #endif /* This must match sig_atomic_t in (currently int) */ #define SIG_ATOMIC_MIN (-__STDINT_EXP(INT_MAX) - 1) -#define SIG_ATOMIC_MAX __STDINT_EXP(INT_MAX) +#define SIG_ATOMIC_MAX (__STDINT_EXP(INT_MAX)) /* This must match ptrdiff_t in (currently long int) */ #ifdef __PTRDIFF_MAX__ -#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define PTRDIFF_MAX (__PTRDIFF_MAX__) #else -#define PTRDIFF_MAX __STDINT_EXP(LONG_MAX) +#define PTRDIFF_MAX (__STDINT_EXP(LONG_MAX)) #endif #define PTRDIFF_MIN (-PTRDIFF_MAX - 1) /* This must match definition in */ #ifndef WCHAR_MIN #ifdef __WCHAR_MIN__ -#define WCHAR_MIN __WCHAR_MIN__ +#define WCHAR_MIN (__WCHAR_MIN__) #elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0) #define WCHAR_MIN (0 + L'\0') #else @@ -416,7 +371,7 @@ typedef __uintptr_t uintptr_t; /* This must match definition in */ #ifndef WCHAR_MAX #ifdef __WCHAR_MAX__ -#define WCHAR_MAX __WCHAR_MAX__ +#define WCHAR_MAX (__WCHAR_MAX__) #elif defined(__WCHAR_UNSIGNED__) || (L'\0' - 1 > 0) #define WCHAR_MAX (0xffffffffu + L'\0') #else @@ -426,14 +381,14 @@ typedef __uintptr_t uintptr_t; /* wint_t is unsigned int on almost all GCC targets. */ #ifdef __WINT_MAX__ -#define WINT_MAX __WINT_MAX__ +#define WINT_MAX (__WINT_MAX__) #else #define WINT_MAX (__STDINT_EXP(INT_MAX) * 2U + 1U) #endif #ifdef __WINT_MIN__ -#define WINT_MIN __WINT_MIN__ +#define WINT_MIN (__WINT_MIN__) #else -#define WINT_MIN 0U +#define WINT_MIN (0U) #endif /** Macros for minimum-width integer constant expressions */ @@ -465,7 +420,7 @@ typedef __uintptr_t uintptr_t; #define INT32_C(x) __INT32_C(x) #define UINT32_C(x) __UINT32_C(x) #else -#if __have_long32 +#if defined (_INT32_EQ_LONG) #define INT32_C(x) x##L #define UINT32_C(x) x##UL #else diff --git a/libc/xtensa-lx106-elf/include/stdio.h b/libc/xtensa-lx106-elf/include/stdio.h index e336ee6..ee0f612 100644 --- a/libc/xtensa-lx106-elf/include/stdio.h +++ b/libc/xtensa-lx106-elf/include/stdio.h @@ -35,9 +35,22 @@ #include #include +/* typedef only __gnuc_va_list, used throughout the header */ #define __need___va_list #include +/* typedef va_list only when required */ +#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE +#ifdef __GNUC__ +#ifndef _VA_LIST_DEFINED +typedef __gnuc_va_list va_list; +#define _VA_LIST_DEFINED +#endif +#else /* !__GNUC__ */ +#include +#endif +#endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */ + /* * defines __FILE, _fpos_t. * They must be defined there because struct _reent needs them (and we don't @@ -49,7 +62,10 @@ _BEGIN_STD_C +#if !defined(__FILE_defined) typedef __FILE FILE; +# define __FILE_defined +#endif #ifdef __CYGWIN__ typedef _fpos64_t fpos_t; @@ -125,7 +141,7 @@ typedef _fpos64_t fpos64_t; #define L_tmpnam FILENAME_MAX #endif -#ifndef __STRICT_ANSI__ +#if __BSD_VISIBLE || __XSI_VISIBLE #define P_tmpdir "/tmp" #endif @@ -161,6 +177,12 @@ typedef _fpos64_t fpos64_t; #endif #endif +#if __POSIX_VISIBLE +char * _EXFUN(ctermid, (char *)); +#endif +#if __XSI_VISIBLE && __XSI_VISIBLE < 600 +char * _EXFUN(cuserid, (char *)); +#endif FILE * _EXFUN(tmpfile, (void)); char * _EXFUN(tmpnam, (char *)); #if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 @@ -227,7 +249,7 @@ int _EXFUN(rename, (const char *, const char *)); int _EXFUN(_rename, (const char *, const char *)); #endif #endif -#if !defined(__STRICT_ANSI__) || defined(__USE_XOPEN2K) +#if __LARGEFILE_VISIBLE || __POSIX_VISIBLE >= 200112 #ifdef _COMPILING_NEWLIB int _EXFUN(fseeko, (FILE *, _off_t, int)); _off_t _EXFUN(ftello, ( FILE *)); @@ -239,16 +261,32 @@ off_t _EXFUN(ftello, ( FILE *)); #if __GNU_VISIBLE int _EXFUN(fcloseall, (_VOID)); #endif -#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L) #ifndef _REENT_ONLY +#if __ISO_C_VISIBLE >= 1999 +int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); +int _EXFUN(vsnprintf, (char *__restrict, size_t, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); +int _EXFUN(vfscanf, (FILE *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +int _EXFUN(vscanf, (const char *, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); +int _EXFUN(vsscanf, (const char *__restrict, const char *__restrict, __VALIST) + _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +#endif +#if __GNU_VISIBLE +int _EXFUN(asprintf, (char **__restrict, const char *__restrict, ...) + _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); +int _EXFUN(vasprintf, (char **, const char *, __VALIST) + _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); +#endif +#if __MISC_VISIBLE /* Newlib-specific */ int _EXFUN(asiprintf, (char **, const char *, ...) _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); char * _EXFUN(asniprintf, (char *, size_t *, const char *, ...) _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); char * _EXFUN(asnprintf, (char *__restrict, size_t *__restrict, const char *__restrict, ...) _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(asprintf, (char **__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); #ifndef diprintf int _EXFUN(diprintf, (int, const char *, ...) _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); @@ -265,8 +303,6 @@ int _EXFUN(siprintf, (char *, const char *, ...) _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); int _EXFUN(siscanf, (const char *, const char *, ...) _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); int _EXFUN(sniprintf, (char *, size_t, const char *, ...) _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); int _EXFUN(vasiprintf, (char **, const char *, __VALIST) @@ -275,50 +311,50 @@ char * _EXFUN(vasniprintf, (char *, size_t *, const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); char * _EXFUN(vasnprintf, (char *, size_t *, const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vasprintf, (char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); int _EXFUN(vdiprintf, (int, const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); int _EXFUN(vfiprintf, (FILE *, const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); int _EXFUN(vfiscanf, (FILE *, const char *, __VALIST) _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(vfscanf, (FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); int _EXFUN(viprintf, (const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); int _EXFUN(viscanf, (const char *, __VALIST) _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); -int _EXFUN(vscanf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); int _EXFUN(vsiprintf, (char *, const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); int _EXFUN(vsiscanf, (const char *, const char *, __VALIST) _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vsnprintf, (char *__restrict, size_t, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vsscanf, (const char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); +#endif /* __MISC_VISIBLE */ #endif /* !_REENT_ONLY */ -#endif /* !__STRICT_ANSI__ */ /* * Routines in POSIX 1003.1:2001. */ -#ifndef __STRICT_ANSI__ +#if __POSIX_VISIBLE #ifndef _REENT_ONLY FILE * _EXFUN(fdopen, (int, const char *)); #endif int _EXFUN(fileno, (FILE *)); -int _EXFUN(getw, (FILE *)); +#endif +#if __MISC_VISIBLE || __POSIX_VISIBLE >= 199209 int _EXFUN(pclose, (FILE *)); FILE * _EXFUN(popen, (const char *, const char *)); -int _EXFUN(putw, (int, FILE *)); +#endif + +#if __BSD_VISIBLE void _EXFUN(setbuffer, (FILE *, char *, int)); int _EXFUN(setlinebuf, (FILE *)); +#endif + +#if __MISC_VISIBLE || (__XSI_VISIBLE && __POSIX_VISIBLE < 200112) +int _EXFUN(getw, (FILE *)); +int _EXFUN(putw, (int, FILE *)); +#endif +#if __MISC_VISIBLE || __POSIX_VISIBLE int _EXFUN(getc_unlocked, (FILE *)); int _EXFUN(getchar_unlocked, (void)); void _EXFUN(flockfile, (FILE *)); @@ -326,13 +362,13 @@ int _EXFUN(ftrylockfile, (FILE *)); void _EXFUN(funlockfile, (FILE *)); int _EXFUN(putc_unlocked, (int, FILE *)); int _EXFUN(putchar_unlocked, (int)); -#endif /* ! __STRICT_ANSI__ */ +#endif /* * Routines in POSIX 1003.1:200x. */ -#ifndef __STRICT_ANSI__ +#if __POSIX_VISIBLE >= 200809 # ifndef _REENT_ONLY # ifndef dprintf int _EXFUN(dprintf, (int, const char *__restrict, ...) @@ -342,13 +378,16 @@ FILE * _EXFUN(fmemopen, (void *__restrict, size_t, const char *__restrict)); /* getdelim - see __getdelim for now */ /* getline - see __getline for now */ FILE * _EXFUN(open_memstream, (char **, size_t *)); -#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 -int _EXFUN(renameat, (int, const char *, int, const char *)); -#endif int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST) _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); # endif #endif +#if __ATFILE_VISIBLE +int _EXFUN(renameat, (int, const char *, int, const char *)); +# ifdef __CYGWIN__ +int _EXFUN(renameat2, (int, const char *, int, const char *, unsigned int)); +# endif +#endif /* * Recursive versions of the above. @@ -492,7 +531,7 @@ int _EXFUN(fpurge, (FILE *)); ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *)); ssize_t _EXFUN(__getline, (char **, size_t *, FILE *)); -#if __BSD_VISIBLE +#if __MISC_VISIBLE void _EXFUN(clearerr_unlocked, (FILE *)); int _EXFUN(feof_unlocked, (FILE *)); int _EXFUN(ferror_unlocked, (FILE *)); @@ -542,7 +581,7 @@ int _EXFUN(__swbuf_r, (struct _reent *, int, FILE *)); * Stdio function-access interface. */ -#ifndef __STRICT_ANSI__ +#if __BSD_VISIBLE # ifdef __LARGE64_FILES FILE *_EXFUN(funopen,(const _PTR __cookie, int (*__readfn)(_PTR __c, char *__buf, @@ -579,7 +618,9 @@ FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, (fpos_t (*)())0, (int (*)())0) # define fwopen(__cookie, __fn) funopen(__cookie, (int (*)())0, __fn, \ (fpos_t (*)())0, (int (*)())0) +#endif /* __BSD_VISIBLE */ +#if __GNU_VISIBLE typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n); typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf, size_t __n); @@ -603,7 +644,7 @@ FILE *_EXFUN(fopencookie,(void *__cookie, const char *__mode, cookie_io_functions_t __functions)); FILE *_EXFUN(_fopencookie_r,(struct _reent *, void *__cookie, const char *__mode, cookie_io_functions_t __functions)); -#endif /* ! __STRICT_ANSI__ */ +#endif /* __GNU_VISIBLE */ #ifndef __CUSTOM_FILE_IO__ /* @@ -642,10 +683,12 @@ _ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p) #define __sgetc_r(__ptr, __p) __sgetc_raw_r(__ptr, __p) #endif -#ifdef _never /* __GNUC__ */ -/* If this inline is actually used, then systems using coff debugging - info get hopelessly confused. 21sept93 rich@cygnus.com. */ +#ifdef __GNUC__ _ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { +#ifdef __SCLE + if ((_p->_flags & __SCLE) && _c == '\n') + __sputc_r (_ptr, '\r', _p); +#endif if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) return (*_p->_p++ = _c); else @@ -678,50 +721,79 @@ _ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { #define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) #define __sfileno(p) ((p)->_file) +#ifndef __cplusplus #ifndef _REENT_SMALL #define feof(p) __sfeof(p) #define ferror(p) __sferror(p) #define clearerr(p) __sclearerr(p) -#if __BSD_VISIBLE +#if __MISC_VISIBLE #define feof_unlocked(p) __sfeof(p) #define ferror_unlocked(p) __sferror(p) #define clearerr_unlocked(p) __sclearerr(p) -#endif /* __BSD_VISIBLE */ +#endif /* __MISC_VISIBLE */ #endif /* _REENT_SMALL */ -#if 0 /*ndef __STRICT_ANSI__ - FIXME: must initialize stdio first, use fn */ +#if 0 /* __POSIX_VISIBLE - FIXME: must initialize stdio first, use fn */ #define fileno(p) __sfileno(p) #endif -#ifndef __CYGWIN__ -#ifndef lint -#define getc(fp) __sgetc_r(_REENT, fp) -#define putc(x, fp) __sputc_r(_REENT, x, fp) -#endif /* lint */ -#endif /* __CYGWIN__ */ +static __inline int +_getchar_unlocked(void) +{ + struct _reent *_ptr; -#ifndef __STRICT_ANSI__ + _ptr = _REENT; + return (__sgetc_r(_ptr, _stdin_r(_ptr))); +} + +static __inline int +_putchar_unlocked(int _c) +{ + struct _reent *_ptr; + + _ptr = _REENT; + return (__sputc_r(_ptr, _c, _stdout_r(_ptr))); +} + +#ifdef __SINGLE_THREAD__ +#define getc(_p) __sgetc_r(_REENT, _p) +#define putc(_c, _p) __sputc_r(_REENT, _c, _p) +#define getchar() _getchar_unlocked() +#define putchar(_c) _putchar_unlocked(_c) +#endif /* __SINGLE_THREAD__ */ + +#if __MISC_VISIBLE || __POSIX_VISIBLE +#define getchar_unlocked() _getchar_unlocked() +#define putchar_unlocked(_c) _putchar_unlocked(_c) +#endif +#endif /* __cplusplus */ + +#if __MISC_VISIBLE /* fast always-buffered version, true iff error */ #define fast_putc(x,p) (--(p)->_w < 0 ? \ __swbuf_r(_REENT, (int)(x), p) == EOF : (*(p)->_p = (x), (p)->_p++, 0)) +#endif +#if __GNU_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 600) #define L_cuserid 9 /* posix says it goes in stdio.h :( */ -#ifdef __CYGWIN__ +#endif +#if __POSIX_VISIBLE #define L_ctermid 16 #endif -#endif -#endif /* !__CUSTOM_FILE_IO__ */ +#else /* __CUSTOM_FILE_IO__ */ #define getchar() getc(stdin) #define putchar(x) putc(x, stdout) -#ifndef __STRICT_ANSI__ +#if __MISC_VISIBLE || __POSIX_VISIBLE #define getchar_unlocked() getc_unlocked(stdin) #define putchar_unlocked(x) putc_unlocked(x, stdout) #endif +#endif /* !__CUSTOM_FILE_IO__ */ + _END_STD_C #endif /* _STDIO_H_ */ diff --git a/libc/xtensa-lx106-elf/include/stdlib.h b/libc/xtensa-lx106-elf/include/stdlib.h index 254ddd7..c4e6633 100644 --- a/libc/xtensa-lx106-elf/include/stdlib.h +++ b/libc/xtensa-lx106-elf/include/stdlib.h @@ -26,6 +26,10 @@ #include #endif +#if __GNU_VISIBLE +#include +#endif + _BEGIN_STD_C typedef struct @@ -40,9 +44,7 @@ typedef struct long rem; /* remainder */ } ldiv_t; -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +#if __ISO_C_VISIBLE >= 1999 typedef struct { long long int quot; /* quotient */ @@ -70,9 +72,14 @@ int _EXFUN(__locale_mb_cur_max,(_VOID)); _VOID _EXFUN(abort,(_VOID) _ATTRIBUTE ((__noreturn__))); int _EXFUN(abs,(int)); +#if __BSD_VISIBLE +__uint32_t _EXFUN(arc4random, (void)); +__uint32_t _EXFUN(arc4random_uniform, (__uint32_t)); +void _EXFUN(arc4random_buf, (void *, size_t)); +#endif int _EXFUN(atexit,(_VOID (*__func)(_VOID))); double _EXFUN(atof,(const char *__nptr)); -#ifndef __STRICT_ANSI__ +#if __MISC_VISIBLE float _EXFUN(atoff,(const char *__nptr)); #endif int _EXFUN(atoi,(const char *__nptr)); @@ -92,7 +99,7 @@ char * _EXFUN(getenv,(const char *__string)); char * _EXFUN(_getenv_r,(struct _reent *, const char *__string)); char * _EXFUN(_findenv,(_CONST char *, int *)); char * _EXFUN(_findenv_r,(struct _reent *, _CONST char *, int *)); -#ifndef __STRICT_ANSI__ +#if __POSIX_VISIBLE >= 200809 extern char *suboptarg; /* getsubopt(3) external variable */ int _EXFUN(getsubopt,(char **, char * const *, char **)); #endif @@ -109,48 +116,64 @@ size_t _EXFUN(mbstowcs,(wchar_t *__restrict, const char *__restrict, size_t)); size_t _EXFUN(_mbstowcs_r,(struct _reent *, wchar_t *__restrict, const char *__restrict, size_t, _mbstate_t *)); size_t _EXFUN(wcstombs,(char *__restrict, const wchar_t *__restrict, size_t)); size_t _EXFUN(_wcstombs_r,(struct _reent *, char *__restrict, const wchar_t *__restrict, size_t, _mbstate_t *)); -#ifndef __STRICT_ANSI__ #ifndef _REENT_ONLY +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 char * _EXFUN(mkdtemp,(char *)); +#endif +#if __GNU_VISIBLE int _EXFUN(mkostemp,(char *, int)); int _EXFUN(mkostemps,(char *, int, int)); +#endif +#if __MISC_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 4 int _EXFUN(mkstemp,(char *)); +#endif +#if __MISC_VISIBLE int _EXFUN(mkstemps,(char *, int)); +#endif #if (__GNUC__ < 4) || defined(__XTENSA__) char * _EXFUN(mktemp,(char *)); #else -char * _EXFUN(mktemp,(char *) _ATTRIBUTE ((__warning__ ("the use of `mktemp' is dangerous; use `mkstemp' instead")))); +#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112) +char * _EXFUN(mktemp,(char *) _ATTRIBUTE ((__deprecated__("the use of `mktemp' is dangerous; use `mkstemp' instead")))); #endif #endif +#endif /* !_REENT_ONLY */ char * _EXFUN(_mkdtemp_r, (struct _reent *, char *)); int _EXFUN(_mkostemp_r, (struct _reent *, char *, int)); int _EXFUN(_mkostemps_r, (struct _reent *, char *, int, int)); int _EXFUN(_mkstemp_r, (struct _reent *, char *)); int _EXFUN(_mkstemps_r, (struct _reent *, char *, int)); #if (__GNUC__ < 4) || defined(__XTENSA__) -char * _EXFUN(_mktemp_r, (struct _reent *, char *)); +char * _EXFUN(_mktemp_r, (struct _reent *, char *)); #else -char * _EXFUN(_mktemp_r, (struct _reent *, char *) _ATTRIBUTE ((__warning__ ("the use of `mktemp' is dangerous; use `mkstemp' instead")))); -#endif +char * _EXFUN(_mktemp_r, (struct _reent *, char *) _ATTRIBUTE ((__deprecated__("the use of `mktemp' is dangerous; use `mkstemp' instead")))); #endif _VOID _EXFUN(qsort,(_PTR __base, size_t __nmemb, size_t __size, __compar_fn_t _compar)); int _EXFUN(rand,(_VOID)); _PTR _EXFUN_NOTHROW(realloc,(_PTR __r, size_t __size)); -#ifndef __STRICT_ANSI__ +#if __BSD_VISIBLE +void *reallocarray(void *, size_t, size_t) __result_use_check __alloc_size(2) + __alloc_size(3); _PTR _EXFUN(reallocf,(_PTR __r, size_t __size)); +#endif +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 char * _EXFUN(realpath, (const char *__restrict path, char *__restrict resolved_path)); #endif +#if __BSD_VISIBLE +int _EXFUN(rpmatch, (const char *response)); +#endif +#if __XSI_VISIBLE +_VOID _EXFUN(setkey, (const char *__key)); +#endif _VOID _EXFUN(srand,(unsigned __seed)); double _EXFUN(strtod,(const char *__restrict __n, char **__restrict __end_PTR)); double _EXFUN(_strtod_r,(struct _reent *,const char *__restrict __n, char **__restrict __end_PTR)); -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +#if __ISO_C_VISIBLE >= 1999 float _EXFUN(strtof,(const char *__restrict __n, char **__restrict __end_PTR)); #endif -#ifndef __STRICT_ANSI__ +#if __MISC_VISIBLE /* the following strtodf interface is deprecated...use strtof instead */ -# ifndef strtodf +# ifndef strtodf # define strtodf strtof # endif #endif @@ -159,26 +182,45 @@ long _EXFUN(_strtol_r,(struct _reent *,const char *__restrict __n, char **__rest unsigned long _EXFUN(strtoul,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); unsigned long _EXFUN(_strtoul_r,(struct _reent *,const char *__restrict __n, char **__restrict __end_PTR, int __base)); +#if __GNU_VISIBLE +double strtod_l (const char *__restrict, char **__restrict, locale_t); +float strtof_l (const char *__restrict, char **__restrict, locale_t); +#ifdef _HAVE_LONG_DOUBLE +extern long double strtold_l (const char *__restrict, char **__restrict, + locale_t); +#endif /* _HAVE_LONG_DOUBLE */ +long strtol_l (const char *__restrict, char **__restrict, int, locale_t); +unsigned long strtoul_l (const char *__restrict, char **__restrict, int, + locale_t __loc); +long long strtoll_l (const char *__restrict, char **__restrict, int, locale_t); +unsigned long long strtoull_l (const char *__restrict, char **__restrict, int, + locale_t __loc); +#endif + int _EXFUN(system,(const char *__string)); -#ifndef __STRICT_ANSI__ +#if __SVID_VISIBLE || __XSI_VISIBLE >= 4 long _EXFUN(a64l,(const char *__input)); char * _EXFUN(l64a,(long __input)); char * _EXFUN(_l64a_r,(struct _reent *,long __input)); +#endif +#if __MISC_VISIBLE int _EXFUN(on_exit,(_VOID (*__func)(int, _PTR),_PTR __arg)); -#endif /* ! __STRICT_ANSI__ */ -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +#endif +#if __ISO_C_VISIBLE >= 1999 _VOID _EXFUN(_Exit,(int __status) _ATTRIBUTE ((__noreturn__))); #endif -#ifndef __STRICT_ANSI__ +#if __SVID_VISIBLE || __XSI_VISIBLE int _EXFUN(putenv,(char *__string)); +#endif int _EXFUN(_putenv_r,(struct _reent *, char *__string)); _PTR _EXFUN(_reallocf_r,(struct _reent *, _PTR, size_t)); +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 int _EXFUN(setenv,(const char *__string, const char *__value, int __overwrite)); +#endif int _EXFUN(_setenv_r,(struct _reent *, const char *__string, const char *__value, int __overwrite)); +#if __XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112 char * _EXFUN(gcvt,(double,int,char *)); char * _EXFUN(gcvtf,(float,int,char *)); char * _EXFUN(fcvt,(double,int,int *,int *)); @@ -187,15 +229,18 @@ char * _EXFUN(ecvt,(double,int,int *,int *)); char * _EXFUN(ecvtbuf,(double, int, int*, int*, char *)); char * _EXFUN(fcvtbuf,(double, int, int*, int*, char *)); char * _EXFUN(ecvtf,(float,int,int *,int *)); -char * _EXFUN(dtoa,(double, int, int, int *, int*, char**)); #endif char * _EXFUN(__itoa,(int, char *, int)); char * _EXFUN(__utoa,(unsigned, char *, int)); -#ifndef __STRICT_ANSI__ +#if __MISC_VISIBLE char * _EXFUN(itoa,(int, char *, int)); char * _EXFUN(utoa,(unsigned, char *, int)); +#endif +#if __POSIX_VISIBLE int _EXFUN(rand_r,(unsigned *__seed)); +#endif +#if __SVID_VISIBLE || __XSI_VISIBLE double _EXFUN(drand48,(_VOID)); double _EXFUN(_drand48_r,(struct _reent *)); double _EXFUN(erand48,(unsigned short [3])); @@ -216,45 +261,42 @@ unsigned short * _EXFUN(_seed48_r,(struct _reent *, unsigned short [3])); _VOID _EXFUN(srand48,(long)); _VOID _EXFUN(_srand48_r,(struct _reent *, long)); -#endif /* ! __STRICT_ANSI__ */ -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +#endif /* __SVID_VISIBLE || __XSI_VISIBLE */ +#if __SVID_VISIBLE || __XSI_VISIBLE >= 4 || __BSD_VISIBLE +char * _EXFUN(initstate,(unsigned, char *, size_t)); +long _EXFUN(random,(_VOID)); +char * _EXFUN(setstate,(char *)); +_VOID _EXFUN(srandom,(unsigned)); +#endif +#if __ISO_C_VISIBLE >= 1999 long long _EXFUN(atoll,(const char *__nptr)); #endif -#ifndef __STRICT_ANSI__ long long _EXFUN(_atoll_r,(struct _reent *, const char *__nptr)); -#endif /* ! __STRICT_ANSI__ */ -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +#if __ISO_C_VISIBLE >= 1999 long long _EXFUN(llabs,(long long)); lldiv_t _EXFUN(lldiv,(long long __numer, long long __denom)); long long _EXFUN(strtoll,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); #endif -#ifndef __STRICT_ANSI__ long long _EXFUN(_strtoll_r,(struct _reent *, const char *__restrict __n, char **__restrict __end_PTR, int __base)); -#endif /* ! __STRICT_ANSI__ */ -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +#if __ISO_C_VISIBLE >= 1999 unsigned long long _EXFUN(strtoull,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); #endif -#ifndef __STRICT_ANSI__ unsigned long long _EXFUN(_strtoull_r,(struct _reent *, const char *__restrict __n, char **__restrict __end_PTR, int __base)); #ifndef __CYGWIN__ +#if __MISC_VISIBLE _VOID _EXFUN(cfree,(_PTR)); +#endif +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 int _EXFUN(unsetenv,(const char *__string)); +#endif int _EXFUN(_unsetenv_r,(struct _reent *, const char *__string)); -#endif +#endif /* !__CYGWIN__ */ -#ifdef __rtems__ -int _EXFUN(posix_memalign,(void **, size_t, size_t)); +#if __POSIX_VISIBLE >= 200112 +int _EXFUN(__nonnull (1) posix_memalign,(void **, size_t, size_t)); #endif -#endif /* ! __STRICT_ANSI__ */ - char * _EXFUN(_dtoa_r,(struct _reent *, double, int, int, int *, int*, char**)); #ifndef __CYGWIN__ _PTR _EXFUN_NOTHROW(_malloc_r,(struct _reent *, size_t)); @@ -271,7 +313,9 @@ _VOID _EXFUN(__eprintf,(const char *, const char *, unsigned int, const char *)) _BSD_SOURCE, you get the BSD version; otherwise you get the GNU version. We want that #undef qsort_r will still let you invoke the underlying function, but that requires gcc support. */ -#ifdef _BSD_SOURCE +#if __GNU_VISIBLE +_VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, int (*_compar)(const _PTR, const _PTR, _PTR), _PTR __thunk)); +#elif __BSD_VISIBLE # ifdef __GNUC__ _VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, int (*_compar)(_PTR, const _PTR, const _PTR))) __asm__ (__ASMNAME ("__bsd_qsort_r")); @@ -279,19 +323,27 @@ _VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, _VOID _EXFUN(__bsd_qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, int (*_compar)(_PTR, const _PTR, const _PTR))); # define qsort_r __bsd_qsort_r # endif -#elif __GNU_VISIBLE -_VOID _EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, int (*_compar)(const _PTR, const _PTR, _PTR), _PTR __thunk)); #endif /* On platforms where long double equals double. */ #ifdef _HAVE_LONG_DOUBLE -#if !defined(__STRICT_ANSI__) || \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ - (defined(__cplusplus) && __cplusplus >= 201103L) +extern long double _strtold_r (struct _reent *, const char *__restrict, char **__restrict); +#if __ISO_C_VISIBLE >= 1999 extern long double strtold (const char *__restrict, char **__restrict); #endif #endif /* _HAVE_LONG_DOUBLE */ +/* + * If we're in a mode greater than C99, expose C11 functions. + */ +#if __ISO_C_VISIBLE >= 2011 +void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) + __alloc_size(2); +int at_quick_exit(void (*)(void)); +_Noreturn void + quick_exit(int); +#endif /* __ISO_C_VISIBLE >= 2011 */ + _END_STD_C #endif /* _STDLIB_H_ */ diff --git a/libc/xtensa-lx106-elf/include/string.h b/libc/xtensa-lx106-elf/include/string.h index af5c9da..9c536f3 100644 --- a/libc/xtensa-lx106-elf/include/string.h +++ b/libc/xtensa-lx106-elf/include/string.h @@ -16,6 +16,14 @@ #define __need_NULL #include +#if __POSIX_VISIBLE >= 200809 +#include +#endif + +#if __BSD_VISIBLE +#include +#endif + _BEGIN_STD_C _PTR _EXFUN(memchr,(const _PTR, int, size_t)); @@ -43,57 +51,43 @@ char *_EXFUN(strtok,(char *__restrict, const char *__restrict)); #endif size_t _EXFUN(strxfrm,(char *__restrict, const char *__restrict, size_t)); -#if __POSIX_VISIBLE +#if __POSIX_VISIBLE >= 200809 +int strcoll_l (const char *, const char *, locale_t); +char *strerror_l (int, locale_t); +size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t); +#endif +#if __MISC_VISIBLE || __POSIX_VISIBLE char *_EXFUN(strtok_r,(char *__restrict, const char *__restrict, char **__restrict)); #endif #if __BSD_VISIBLE -int _EXFUN(bcmp,(const void *, const void *, size_t)); -void _EXFUN(bcopy,(const void *, void *, size_t)); -void _EXFUN(bzero,(void *, size_t)); -int _EXFUN(ffs,(int)); -char *_EXFUN(index,(const char *, int)); +int _EXFUN(timingsafe_bcmp,(const void *, const void *, size_t)); +int _EXFUN(timingsafe_memcmp,(const void *, const void *, size_t)); #endif -#if __BSD_VISIBLE || __XSI_VISIBLE +#if __MISC_VISIBLE || __POSIX_VISIBLE _PTR _EXFUN(memccpy,(_PTR __restrict, const _PTR __restrict, int, size_t)); #endif #if __GNU_VISIBLE _PTR _EXFUN(mempcpy,(_PTR, const _PTR, size_t)); _PTR _EXFUN(memmem, (const _PTR, size_t, const _PTR, size_t)); -#endif _PTR _EXFUN(memrchr,(const _PTR, int, size_t)); -#if __GNU_VISIBLE _PTR _EXFUN(rawmemchr,(const _PTR, int)); #endif -#if __BSD_VISIBLE -char *_EXFUN(rindex,(const char *, int)); -#endif +#if __POSIX_VISIBLE >= 200809 char *_EXFUN(stpcpy,(char *__restrict, const char *__restrict)); char *_EXFUN(stpncpy,(char *__restrict, const char *__restrict, size_t)); -#if __BSD_VISIBLE || __POSIX_VISIBLE -int _EXFUN(strcasecmp,(const char *, const char *)); #endif #if __GNU_VISIBLE char *_EXFUN(strcasestr,(const char *, const char *)); char *_EXFUN(strchrnul,(const char *, int)); #endif -#if __XSI_VISIBLE >= 500 +#if __MISC_VISIBLE || __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 4 char *_EXFUN(strdup,(const char *)); #endif -#ifndef __STRICT_ANSI__ char *_EXFUN(_strdup_r,(struct _reent *, const char *)); -#endif -#if __XSI_VISIBLE >= 700 +#if __POSIX_VISIBLE >= 200809 char *_EXFUN(strndup,(const char *, size_t)); #endif - -#ifndef __STRICT_ANSI__ char *_EXFUN(_strndup_r,(struct _reent *, const char *, size_t)); -#endif - -#if __GNU_VISIBLE -int _EXFUN(ffsl,(long)); -int _EXFUN(ffsll, (long long)); -#endif /* There are two common strerror_r variants. If you request _GNU_SOURCE, you get the GNU version; otherwise you get the POSIX @@ -101,10 +95,13 @@ int _EXFUN(ffsll, (long long)); invoke the underlying function, but that requires gcc support. */ #if __GNU_VISIBLE char *_EXFUN(strerror_r,(int, char *, size_t)); -#else +#elif __POSIX_VISIBLE >= 200112 # ifdef __GNUC__ int _EXFUN(strerror_r,(int, char *, size_t)) - __asm__ (__ASMNAME ("__xpg_strerror_r")); +#ifdef __ASMNAME + __asm__ (__ASMNAME ("__xpg_strerror_r")) +#endif + ; # else int _EXFUN(__xpg_strerror_r,(int, char *, size_t)); # define strerror_r __xpg_strerror_r @@ -118,22 +115,17 @@ char * _EXFUN(_strerror_r, (struct _reent *, int, int, int *)); size_t _EXFUN(strlcat,(char *, const char *, size_t)); size_t _EXFUN(strlcpy,(char *, const char *, size_t)); #endif -#if __BSD_VISIBLE || __POSIX_VISIBLE -int _EXFUN(strncasecmp,(const char *, const char *, size_t)); -#endif -#if !defined(__STRICT_ANSI__) || __POSIX_VISIBLE >= 200809 || \ - __XSI_VISIBLE >= 700 +#if __POSIX_VISIBLE >= 200809 size_t _EXFUN(strnlen,(const char *, size_t)); #endif #if __BSD_VISIBLE char *_EXFUN(strsep,(char **, const char *)); #endif +#if __BSD_VISIBLE +char *strnstr(const char *, const char *, size_t) __pure; +#endif -/* - * The origin of these is unknown to me so I am conditionalizing them - * on __STRICT_ANSI__. Finetuning this is definitely needed. --joel - */ -#if !defined(__STRICT_ANSI__) +#if __MISC_VISIBLE char *_EXFUN(strlwr,(char *)); char *_EXFUN(strupr,(char *)); #endif @@ -146,19 +138,39 @@ char *_EXFUN(strsignal, (int __signo)); int _EXFUN(strtosigno, (const char *__name)); #endif -#if defined _GNU_SOURCE && defined __GNUC__ +#if __GNU_VISIBLE +int _EXFUN(strverscmp,(const char *, const char *)); +#endif + +#if __GNU_VISIBLE && defined(__GNUC__) #define strdupa(__s) \ - (__extension__ ({const char *__in = (__s); \ - size_t __len = strlen (__in) + 1; \ - char * __out = (char *) __builtin_alloca (__len); \ - (char *) memcpy (__out, __in, __len);})) + (__extension__ ({const char *__sin = (__s); \ + size_t __len = strlen (__sin) + 1; \ + char * __sout = (char *) __builtin_alloca (__len); \ + (char *) memcpy (__sout, __sin, __len);})) #define strndupa(__s, __n) \ - (__extension__ ({const char *__in = (__s); \ - size_t __len = strnlen (__in, (__n)) + 1; \ - char *__out = (char *) __builtin_alloca (__len); \ - __out[__len-1] = '\0'; \ - (char *) memcpy (__out, __in, __len-1);})) -#endif /* _GNU_SOURCE && __GNUC__ */ + (__extension__ ({const char *__sin = (__s); \ + size_t __len = strnlen (__sin, (__n)) + 1; \ + char *__sout = (char *) __builtin_alloca (__len); \ + __sout[__len-1] = '\0'; \ + (char *) memcpy (__sout, __sin, __len-1);})) +#endif /* __GNU_VISIBLE && __GNUC__ */ + +/* There are two common basename variants. If you do NOT #include + and you do + + #define _GNU_SOURCE + #include + + you get the GNU version. Otherwise you get the POSIX versionfor which you + should #include i for the function prototype. POSIX requires that + #undef basename will still let you invoke the underlying function. However, + this also implies that the POSIX version is used in this case. That's made + sure here. */ +#if __GNU_VISIBLE && !defined(basename) +# define basename basename +char *_EXFUN(__nonnull (1) basename,(const char *)) __asm__(__ASMNAME("__gnu_basename")); +#endif #include diff --git a/libc/xtensa-lx106-elf/include/strings.h b/libc/xtensa-lx106-elf/include/strings.h index 131d81d..122f2fc 100644 --- a/libc/xtensa-lx106-elf/include/strings.h +++ b/libc/xtensa-lx106-elf/include/strings.h @@ -1,35 +1,78 @@ -/* - * strings.h +/*- + * Copyright (c) 2002 Mike Barcroft + * All rights reserved. * - * Definitions for string operations. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/include/strings.h 272673 2014-10-07 04:54:11Z delphij $ */ #ifndef _STRINGS_H_ -#define _STRINGS_H_ +#define _STRINGS_H_ -#include "_ansi.h" -#include +#include +#include -#include /* for size_t */ +#if __POSIX_VISIBLE >= 200809 +#include +#endif -_BEGIN_STD_C +#ifndef _SIZE_T_DECLARED +typedef __size_t size_t; +#define _SIZE_T_DECLARED +#endif -#if !defined __STRICT_ANSI__ && _POSIX_VERSION < 200809L -/* - * Marked LEGACY in Open Group Base Specifications Issue 6/IEEE Std 1003.1-2004 - * Removed from Open Group Base Specifications Issue 7/IEEE Std 1003.1-2008 - */ -int _EXFUN(bcmp,(const void *, const void *, size_t)); -void _EXFUN(bcopy,(const void *, void *, size_t)); -void _EXFUN(bzero,(void *, size_t)); -char *_EXFUN(index,(const char *, int)); -char *_EXFUN(rindex,(const char *, int)); -#endif /* ! __STRICT_ANSI__ */ +__BEGIN_DECLS +#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112 +int bcmp(const void *, const void *, size_t) __pure; /* LEGACY */ +void bcopy(const void *, void *, size_t); /* LEGACY */ +void bzero(void *, size_t); /* LEGACY */ +#endif +#if __BSD_VISIBLE +void explicit_bzero(void *, size_t); +#endif +#if __MISC_VISIBLE || __POSIX_VISIBLE < 200809 || __XSI_VISIBLE >= 700 +int ffs(int) __pure2; +#endif +#if __GNU_VISIBLE +int ffsl(long) __pure2; +int ffsll(long long) __pure2; +#endif +#if __BSD_VISIBLE +int fls(int) __pure2; +int flsl(long) __pure2; +int flsll(long long) __pure2; +#endif +#if __BSD_VISIBLE || __POSIX_VISIBLE <= 200112 +char *index(const char *, int) __pure; /* LEGACY */ +char *rindex(const char *, int) __pure; /* LEGACY */ +#endif +int strcasecmp(const char *, const char *) __pure; +int strncasecmp(const char *, const char *, size_t) __pure; -int _EXFUN(ffs,(int)); -int _EXFUN(strcasecmp,(const char *, const char *)); -int _EXFUN(strncasecmp,(const char *, const char *, size_t)); - -_END_STD_C +#if __POSIX_VISIBLE >= 200809 +int strcasecmp_l (const char *, const char *, locale_t); +int strncasecmp_l (const char *, const char *, size_t, locale_t); +#endif +__END_DECLS #endif /* _STRINGS_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/_default_fcntl.h b/libc/xtensa-lx106-elf/include/sys/_default_fcntl.h index eb674ae..ede90c4 100644 --- a/libc/xtensa-lx106-elf/include/sys/_default_fcntl.h +++ b/libc/xtensa-lx106-elf/include/sys/_default_fcntl.h @@ -65,7 +65,7 @@ extern "C" { #define O_SEARCH _FEXECSRCH #endif -#ifndef _POSIX_SOURCE +#if __MISC_VISIBLE /* * Flags that work for fcntl(fd, F_SETFL, FXXXX) @@ -97,7 +97,11 @@ extern "C" { #define FEXCL _FEXCL #define FNOCTTY _FNOCTTY -#endif /* !_POSIX_SOURCE */ +#endif /* __MISC_VISIBLE */ + +#if __BSD_VISIBLE +#define FNONBLOCK _FNONBLOCK +#endif /* __BSD_VISIBLE */ /* XXX close on exec request; must match UF_EXCLOSE in user.h */ #define FD_CLOEXEC 1 /* posix */ @@ -108,20 +112,20 @@ extern "C" { #define F_SETFD 2 /* Set fildes flags (close on exec) */ #define F_GETFL 3 /* Get file flags */ #define F_SETFL 4 /* Set file flags */ -#ifndef _POSIX_SOURCE +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 #define F_GETOWN 5 /* Get owner - for ASYNC */ #define F_SETOWN 6 /* Set owner - for ASYNC */ -#endif /* !_POSIX_SOURCE */ +#endif /* __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 */ #define F_GETLK 7 /* Get record-locking information */ #define F_SETLK 8 /* Set or Clear a record-lock (Non-Blocking) */ #define F_SETLKW 9 /* Set or Clear a record-lock (Blocking) */ -#ifndef _POSIX_SOURCE +#if __MISC_VISIBLE #define F_RGETLK 10 /* Test a remote lock to see if it is blocked */ #define F_RSETLK 11 /* Set or unlock a remote lock */ #define F_CNVT 12 /* Convert a fhandle to an open fd */ #define F_RSETLKW 13 /* Set or Clear remote record-lock(Blocking) */ -#endif /* !_POSIX_SOURCE */ -#ifdef __CYGWIN__ +#endif /* __MISC_VISIBLE */ +#if __POSIX_VISIBLE >= 200809 #define F_DUPFD_CLOEXEC 14 /* As F_DUPFD, but set close-on-exec flag */ #endif @@ -129,11 +133,11 @@ extern "C" { #define F_RDLCK 1 /* read lock */ #define F_WRLCK 2 /* write lock */ #define F_UNLCK 3 /* remove lock(s) */ -#ifndef _POSIX_SOURCE +#if __MISC_VISIBLE #define F_UNLKSYS 4 /* remove remote locks for a given system */ -#endif /* !_POSIX_SOURCE */ +#endif /* __MISC_VISIBLE */ -#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined(__CYGWIN__) +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 /* Special descriptor value to denote the cwd in calls to openat(2) etc. */ #define AT_FDCWD -2 @@ -166,7 +170,7 @@ struct flock { }; #endif /* __CYGWIN__ */ -#ifndef _POSIX_SOURCE +#if __MISC_VISIBLE /* extended file segment locking set data type */ struct eflock { short l_type; /* F_RDLCK, F_WRLCK, or F_UNLCK */ @@ -178,13 +182,13 @@ struct eflock { long l_rpid; /* Remote process id wanting this lock */ long l_rsys; /* Remote system id wanting this lock */ }; -#endif /* !_POSIX_SOURCE */ +#endif /* __MISC_VISIBLE */ #include #include /* sigh. for the mode bits for open/creat */ extern int open _PARAMS ((const char *, int, ...)); -#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined(__CYGWIN__) +#if __ATFILE_VISIBLE extern int openat _PARAMS ((int, const char *, int, ...)); #endif extern int creat _PARAMS ((const char *, mode_t)); @@ -192,7 +196,7 @@ extern int fcntl _PARAMS ((int, int, ...)); #if __BSD_VISIBLE extern int flock _PARAMS ((int, int)); #endif -#ifdef __CYGWIN__ +#if __GNU_VISIBLE #include extern int futimesat _PARAMS ((int, const char *, const struct timeval *)); #endif diff --git a/libc/xtensa-lx106-elf/include/sys/_intsup.h b/libc/xtensa-lx106-elf/include/sys/_intsup.h index fa78426..88d7400 100644 --- a/libc/xtensa-lx106-elf/include/sys/_intsup.h +++ b/libc/xtensa-lx106-elf/include/sys/_intsup.h @@ -4,8 +4,6 @@ * * Permission to use, copy, modify, and distribute this software * is freely granted, provided that this notice is preserved. - * - * Modified for xtensa arch & non-long int32_t, removes automatic setting of __have_long32. */ #ifndef _SYS__INTSUP_H @@ -13,8 +11,185 @@ #include +#if __GNUC_PREREQ (3, 2) +/* gcc > 3.2 implicitly defines the values we are interested */ #define __STDINT_EXP(x) __##x##__ +#else +#define __STDINT_EXP(x) x +#include +#endif -#define __have_longlong64 1 +/* Determine how intptr_t and intN_t fastN_t and leastN_t are defined by gcc + for this target. This is used to determine the correct printf() constant in + inttypes.h and other constants in stdint.h. + So we end up with + ?(signed|unsigned) char == 0 + ?(signed|unsigned) short == 1 + ?(signed|unsigned) int == 2 + ?(signed|unsigned) short int == 3 + ?(signed|unsigned) long == 4 + ?(signed|unsigned) long int == 6 + ?(signed|unsigned) long long == 8 + ?(signed|unsigned) long long int == 10 + */ +#pragma push_macro("signed") +#pragma push_macro("unsigned") +#pragma push_macro("char") +#pragma push_macro("short") +#pragma push_macro("__int20") +#pragma push_macro("int") +#pragma push_macro("long") +#undef signed +#undef unsigned +#undef char +#undef short +#undef int +#undef __int20 +#undef long +#define signed +0 +#define unsigned +0 +#define char +0 +#define short +1 +#define __int20 +2 +#define int +2 +#define long +4 +#if (__INTPTR_TYPE__ == 8 || __INTPTR_TYPE__ == 10) +#define _INTPTR_EQ_LONGLONG +#elif (__INTPTR_TYPE__ == 4 || __INTPTR_TYPE__ == 6) +#define _INTPTR_EQ_LONG +/* Note - the tests for _INTPTR_EQ_INT and _INTPTR_EQ_SHORT are currently + redundant as the values are not used. But one day they may be needed + and so the tests remain. */ +#elif __INTPTR_TYPE__ == 2 +#define _INTPTR_EQ_INT +#elif (__INTPTR_TYPE__ == 1 || __INTPTR_TYPE__ == 3) +#define _INTPTR_EQ_SHORT +#else +#error "Unable to determine type definition of intptr_t" +#endif +#if (__INT32_TYPE__ == 4 || __INT32_TYPE__ == 6) +#define _INT32_EQ_LONG +#elif __INT32_TYPE__ == 2 +/* Nothing to define because int32_t is safe to print as an int. */ +#else +#error "Unable to determine type definition of int32_t" +#endif + +#if (__INT8_TYPE__ == 0) +#define __INT8 "hh" +#elif (__INT8_TYPE__ == 1 || __INT8_TYPE__ == 3) +#define __INT8 "h" +#elif (__INT8_TYPE__ == 2) +#define __INT8 +#elif (__INT8_TYPE__ == 4 || __INT8_TYPE__ == 6) +#define __INT8 "l" +#elif (__INT8_TYPE__ == 8 || __INT8_TYPE__ == 10) +#define __INT8 "ll" +#endif +#if (__INT16_TYPE__ == 1 || __INT16_TYPE__ == 3) +#define __INT16 "h" +#elif (__INT16_TYPE__ == 2) +#define __INT16 +#elif (__INT16_TYPE__ == 4 || __INT16_TYPE__ == 6) +#define __INT16 "l" +#elif (__INT16_TYPE__ == 8 || __INT16_TYPE__ == 10) +#define __INT16 "ll" +#endif +#if (__INT32_TYPE__ == 2) +#define __INT32 +#elif (__INT32_TYPE__ == 4 || __INT32_TYPE__ == 6) +#define __INT32 "l" +#elif (__INT32_TYPE__ == 8 || __INT32_TYPE__ == 10) +#define __INT32 "ll" +#endif +#if (__INT64_TYPE__ == 2) +#define __INT64 +#elif (__INT64_TYPE__ == 4 || __INT64_TYPE__ == 6) +#define __INT64 "l" +#elif (__INT64_TYPE__ == 8 || __INT64_TYPE__ == 10) +#define __INT64 "ll" +#endif +#if (__INT_FAST8_TYPE__ == 0) +#define __FAST8 "hh" +#elif (__INT_FAST8_TYPE__ == 1 || __INT_FAST8_TYPE__ == 3) +#define __FAST8 "h" +#elif (__INT_FAST8_TYPE__ == 2) +#define __FAST8 +#elif (__INT_FAST8_TYPE__ == 4 || __INT_FAST8_TYPE__ == 6) +#define __FAST8 "l" +#elif (__INT_FAST8_TYPE__ == 8 || __INT_FAST8_TYPE__ == 10) +#define __FAST8 "ll" +#endif +#if (__INT_FAST16_TYPE__ == 1 || __INT_FAST16_TYPE__ == 3) +#define __FAST16 "h" +#elif (__INT_FAST16_TYPE__ == 2) +#define __FAST16 +#elif (__INT_FAST16_TYPE__ == 4 || __INT_FAST16_TYPE__ == 6) +#define __FAST16 "l" +#elif (__INT_FAST16_TYPE__ == 8 || __INT_FAST16_TYPE__ == 10) +#define __FAST16 "ll" +#endif +#if (__INT_FAST32_TYPE__ == 2) +#define __FAST32 +#elif (__INT_FAST32_TYPE__ == 4 || __INT_FAST32_TYPE__ == 6) +#define __FAST32 "l" +#elif (__INT_FAST32_TYPE__ == 8 || __INT_FAST32_TYPE__ == 10) +#define __FAST32 "ll" +#endif +#if (__INT_FAST64_TYPE__ == 2) +#define __FAST64 +#elif (__INT_FAST64_TYPE__ == 4 || __INT_FAST64_TYPE__ == 6) +#define __FAST64 "l" +#elif (__INT_FAST64_TYPE__ == 8 || __INT_FAST64_TYPE__ == 10) +#define __FAST64 "ll" +#endif + +#if (__INT_LEAST8_TYPE__ == 0) +#define __LEAST8 "hh" +#elif (__INT_LEAST8_TYPE__ == 1 || __INT_LEAST8_TYPE__ == 3) +#define __LEAST8 "h" +#elif (__INT_LEAST8_TYPE__ == 2) +#define __LEAST8 +#elif (__INT_LEAST8_TYPE__ == 4 || __INT_LEAST8_TYPE__ == 6) +#define __LEAST8 "l" +#elif (__INT_LEAST8_TYPE__ == 8 || __INT_LEAST8_TYPE__ == 10) +#define __LEAST8 "ll" +#endif +#if (__INT_LEAST16_TYPE__ == 1 || __INT_LEAST16_TYPE__ == 3) +#define __LEAST16 "h" +#elif (__INT_LEAST16_TYPE__ == 2) +#define __LEAST16 +#elif (__INT_LEAST16_TYPE__ == 4 || __INT_LEAST16_TYPE__ == 6) +#define __LEAST16 "l" +#elif (__INT_LEAST16_TYPE__ == 8 || __INT_LEAST16_TYPE__ == 10) +#define __LEAST16 "ll" +#endif +#if (__INT_LEAST32_TYPE__ == 2) +#define __LEAST32 +#elif (__INT_LEAST32_TYPE__ == 4 || __INT_LEAST32_TYPE__ == 6) +#define __LEAST32 "l" +#elif (__INT_LEAST32_TYPE__ == 8 || __INT_LEAST32_TYPE__ == 10) +#define __LEAST32 "ll" +#endif +#if (__INT_LEAST64_TYPE__ == 2) +#define __LEAST64 +#elif (__INT_LEAST64_TYPE__ == 4 || __INT_LEAST64_TYPE__ == 6) +#define __LEAST64 "l" +#elif (__INT_LEAST64_TYPE__ == 8 || __INT_LEAST64_TYPE__ == 10) +#define __LEAST64 "ll" +#endif +#undef signed +#undef unsigned +#undef char +#undef short +#undef int +#undef long +#pragma pop_macro("signed") +#pragma pop_macro("unsigned") +#pragma pop_macro("char") +#pragma pop_macro("short") +#pragma pop_macro("__int20") +#pragma pop_macro("int") +#pragma pop_macro("long") #endif /* _SYS__INTSUP_H */ diff --git a/libc/xtensa-lx106-elf/include/sys/_pthreadtypes.h b/libc/xtensa-lx106-elf/include/sys/_pthreadtypes.h new file mode 100644 index 0000000..75e9e1c --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/_pthreadtypes.h @@ -0,0 +1,233 @@ +/* + * Written by Joel Sherrill . + * + * COPYRIGHT (c) 1989-2013, 2015. + * On-Line Applications Research Corporation (OAR). + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION + * OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS + * SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + */ + +#ifndef _SYS__PTHREADTYPES_H_ +#define _SYS__PTHREADTYPES_H_ + +#if defined(_POSIX_THREADS) || __POSIX_VISIBLE >= 199506 + +#include + +/* + * 2.5 Primitive System Data Types, P1003.1c/D10, p. 19. + */ + +#if defined(__XMK__) +typedef unsigned int pthread_t; /* identify a thread */ +#else +typedef __uint32_t pthread_t; /* identify a thread */ +#endif + +/* P1003.1c/D10, p. 118-119 */ +#define PTHREAD_SCOPE_PROCESS 0 +#define PTHREAD_SCOPE_SYSTEM 1 + +/* P1003.1c/D10, p. 111 */ +#define PTHREAD_INHERIT_SCHED 1 /* scheduling policy and associated */ + /* attributes are inherited from */ + /* the calling thread. */ +#define PTHREAD_EXPLICIT_SCHED 2 /* set from provided attribute object */ + +/* P1003.1c/D10, p. 141 */ +#define PTHREAD_CREATE_DETACHED 0 +#define PTHREAD_CREATE_JOINABLE 1 + +#if defined(__XMK__) +typedef struct pthread_attr_s { + int contentionscope; + struct sched_param schedparam; + int detachstate; + void *stackaddr; + size_t stacksize; +} pthread_attr_t; + +#define PTHREAD_STACK_MIN 200 + +#else /* !defined(__XMK__) */ +typedef struct { + int is_initialized; + void *stackaddr; + int stacksize; + int contentionscope; + int inheritsched; + int schedpolicy; + struct sched_param schedparam; + + /* P1003.4b/D8, p. 54 adds cputime_clock_allowed attribute. */ +#if defined(_POSIX_THREAD_CPUTIME) + int cputime_clock_allowed; /* see time.h */ +#endif + int detachstate; +} pthread_attr_t; + +#endif /* !defined(__XMK__) */ + +#if defined(_POSIX_THREAD_PROCESS_SHARED) +/* NOTE: P1003.1c/D10, p. 81 defines following values for process_shared. */ + +#define PTHREAD_PROCESS_PRIVATE 0 /* visible within only the creating process */ +#define PTHREAD_PROCESS_SHARED 1 /* visible too all processes with access to */ + /* the memory where the resource is */ + /* located */ +#endif + +#if defined(_POSIX_THREAD_PRIO_PROTECT) +/* Mutexes */ + +/* Values for blocking protocol. */ + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 +#endif + +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + +/* Values for mutex type */ + +/* The following defines are part of the X/Open System Interface (XSI). */ + +/* + * This type of mutex does not detect deadlock. A thread attempting to + * relock this mutex without first unlocking it shall deadlock. Attempting + * to unlock a mutex locked by a different thread results in undefined + * behavior. Attempting to unlock an unlocked mutex results in undefined + * behavior. + */ +#define PTHREAD_MUTEX_NORMAL 0 + +/* + * A thread attempting to relock this mutex without first unlocking + * it shall succeed in locking the mutex. The relocking deadlock which + * can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with + * this type of mutex. Multiple locks of this mutex shall require the + * same number of unlocks to release the mutex before another thread can + * acquire the mutex. A thread attempting to unlock a mutex which another + * thread has locked shall return with an error. A thread attempting to + * unlock an unlocked mutex shall return with an error. + */ +#define PTHREAD_MUTEX_RECURSIVE 1 + +/* + * This type of mutex provides error checking. A thread attempting + * to relock this mutex without first unlocking it shall return with an + * error. A thread attempting to unlock a mutex which another thread has + * locked shall return with an error. A thread attempting to unlock an + * unlocked mutex shall return with an error. + */ +#define PTHREAD_MUTEX_ERRORCHECK 2 + +/* + * Attempting to recursively lock a mutex of this type results + * in undefined behavior. Attempting to unlock a mutex of this type + * which was not locked by the calling thread results in undefined + * behavior. Attempting to unlock a mutex of this type which is not locked + * results in undefined behavior. An implementation may map this mutex to + * one of the other mutex types. + */ +#define PTHREAD_MUTEX_DEFAULT 3 + +#endif /* !defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) */ + +#if defined(__XMK__) +typedef unsigned int pthread_mutex_t; /* identify a mutex */ + +typedef struct { + int type; +} pthread_mutexattr_t; + +#else /* !defined(__XMK__) */ +typedef __uint32_t pthread_mutex_t; /* identify a mutex */ + +typedef struct { + int is_initialized; +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow mutex to be shared amongst processes */ +#endif +#if defined(_POSIX_THREAD_PRIO_PROTECT) + int prio_ceiling; + int protocol; +#endif +#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) + int type; +#endif + int recursive; +} pthread_mutexattr_t; +#endif /* !defined(__XMK__) */ + +#define _PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) 0xFFFFFFFF) + +/* Condition Variables */ + +typedef __uint32_t pthread_cond_t; /* identify a condition variable */ + +#define _PTHREAD_COND_INITIALIZER ((pthread_cond_t) 0xFFFFFFFF) + +typedef struct { + int is_initialized; + clock_t clock; /* specifiy clock for timeouts */ +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow this to be shared amongst processes */ +#endif +} pthread_condattr_t; /* a condition attribute object */ + +/* Keys */ + +typedef __uint32_t pthread_key_t; /* thread-specific data keys */ + +typedef struct { + int is_initialized; /* is this structure initialized? */ + int init_executed; /* has the initialization routine been run? */ +} pthread_once_t; /* dynamic package initialization */ + +#define _PTHREAD_ONCE_INIT { 1, 0 } /* is initialized and not run */ +#endif /* defined(_POSIX_THREADS) || __POSIX_VISIBLE >= 199506 */ + +/* POSIX Barrier Types */ + +#if defined(_POSIX_BARRIERS) +typedef __uint32_t pthread_barrier_t; /* POSIX Barrier Object */ +typedef struct { + int is_initialized; /* is this structure initialized? */ +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow this to be shared amongst processes */ +#endif +} pthread_barrierattr_t; +#endif /* defined(_POSIX_BARRIERS) */ + +/* POSIX Spin Lock Types */ + +#if defined(_POSIX_SPIN_LOCKS) +typedef __uint32_t pthread_spinlock_t; /* POSIX Spin Lock Object */ +#endif /* defined(_POSIX_SPIN_LOCKS) */ + +/* POSIX Reader/Writer Lock Types */ + +#if defined(_POSIX_READER_WRITER_LOCKS) +typedef __uint32_t pthread_rwlock_t; /* POSIX RWLock Object */ + +#define _PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) 0xFFFFFFFF) + +typedef struct { + int is_initialized; /* is this structure initialized? */ +#if defined(_POSIX_THREAD_PROCESS_SHARED) + int process_shared; /* allow this to be shared amongst processes */ +#endif +} pthread_rwlockattr_t; +#endif /* defined(_POSIX_READER_WRITER_LOCKS) */ + +#endif /* ! _SYS__PTHREADTYPES_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/_sigset.h b/libc/xtensa-lx106-elf/include/sys/_sigset.h new file mode 100644 index 0000000..a9c0d2d --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/_sigset.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 1982, 1986, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)signal.h 8.4 (Berkeley) 5/4/95 + * $FreeBSD$ + */ + +#ifndef _SYS__SIGSET_H_ +#define _SYS__SIGSET_H_ + +typedef unsigned long __sigset_t; + +#endif /* !_SYS__SIGSET_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/_stdint.h b/libc/xtensa-lx106-elf/include/sys/_stdint.h new file mode 100644 index 0000000..21a14d3 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/_stdint.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2004, 2005 by + * Ralf Corsepius, Ulm/Germany. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#ifndef _SYS__STDINT_H +#define _SYS__STDINT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ___int8_t_defined +#ifndef _INT8_T_DECLARED +typedef __int8_t int8_t ; +#define _INT8_T_DECLARED +#endif +#ifndef _UINT8_T_DECLARED +typedef __uint8_t uint8_t ; +#define _UINT8_T_DECLARED +#endif +#define __int8_t_defined 1 +#endif /* ___int8_t_defined */ + +#ifdef ___int16_t_defined +#ifndef _INT16_T_DECLARED +typedef __int16_t int16_t ; +#define _INT16_T_DECLARED +#endif +#ifndef _UINT16_T_DECLARED +typedef __uint16_t uint16_t ; +#define _UINT16_T_DECLARED +#endif +#define __int16_t_defined 1 +#endif /* ___int16_t_defined */ + +#ifdef ___int32_t_defined +#ifndef _INT32_T_DECLARED +typedef __int32_t int32_t ; +#define _INT32_T_DECLARED +#endif +#ifndef _UINT32_T_DECLARED +typedef __uint32_t uint32_t ; +#define _UINT32_T_DECLARED +#endif +#define __int32_t_defined 1 +#endif /* ___int32_t_defined */ + +#ifdef ___int64_t_defined +#ifndef _INT64_T_DECLARED +typedef __int64_t int64_t ; +#define _INT64_T_DECLARED +#endif +#ifndef _UINT64_T_DECLARED +typedef __uint64_t uint64_t ; +#define _UINT64_T_DECLARED +#endif +#define __int64_t_defined 1 +#endif /* ___int64_t_defined */ + +#ifndef _INTMAX_T_DECLARED +typedef __intmax_t intmax_t; +#define _INTMAX_T_DECLARED +#endif + +#ifndef _UINTMAX_T_DECLARED +typedef __uintmax_t uintmax_t; +#define _UINTMAX_T_DECLARED +#endif + +#ifndef _INTPTR_T_DECLARED +typedef __intptr_t intptr_t; +#define _INTPTR_T_DECLARED +#endif + +#ifndef _UINTPTR_T_DECLARED +typedef __uintptr_t uintptr_t; +#define _UINTPTR_T_DECLARED +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS__STDINT_H */ diff --git a/libc/xtensa-lx106-elf/include/sys/_timespec.h b/libc/xtensa-lx106-elf/include/sys/_timespec.h new file mode 100644 index 0000000..7609e4a --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/_timespec.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.5 (Berkeley) 5/4/95 + * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp + * $FreeBSD$ + */ + +#ifndef _SYS__TIMESPEC_H_ +#define _SYS__TIMESPEC_H_ + +#include + +#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED) +typedef _TIME_T_ time_t; +#define __time_t_defined +#define _TIME_T_DECLARED +#endif + +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* and nanoseconds */ +}; + +#endif /* !_SYS__TIMESPEC_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/_timeval.h b/libc/xtensa-lx106-elf/include/sys/_timeval.h new file mode 100644 index 0000000..676a0b8 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/_timeval.h @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2002 Mike Barcroft + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS__TIMEVAL_H_ +#define _SYS__TIMEVAL_H_ + +#include + +#ifndef _SUSECONDS_T_DECLARED +typedef __suseconds_t suseconds_t; +#define _SUSECONDS_T_DECLARED +#endif + +#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED) +typedef _TIME_T_ time_t; +#define __time_t_defined +#define _TIME_T_DECLARED +#endif + +/* This define is also used outside of Newlib, e.g. in MinGW-w64 */ +#ifndef _TIMEVAL_DEFINED +#define _TIMEVAL_DEFINED + +/* + * Structure returned by gettimeofday(2) system call, and used in other calls. + */ +struct timeval { + time_t tv_sec; /* seconds */ + suseconds_t tv_usec; /* and microseconds */ +}; + +#if __BSD_VISIBLE +#ifndef _KERNEL /* NetBSD/OpenBSD compatible interfaces */ + +#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) +#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +#define timercmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_usec cmp (uvp)->tv_usec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) +#define timeradd(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ + if ((vvp)->tv_usec >= 1000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_usec -= 1000000; \ + } \ + } while (0) +#define timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif +#endif /* __BSD_VISIBLE */ + +#endif /* _TIMEVAL_DEFINED */ + +#endif /* !_SYS__TIMEVAL_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/_types.h b/libc/xtensa-lx106-elf/include/sys/_types.h index 07bc276..72e1dc1 100644 --- a/libc/xtensa-lx106-elf/include/sys/_types.h +++ b/libc/xtensa-lx106-elf/include/sys/_types.h @@ -2,51 +2,141 @@ /* This file defines various typedefs needed by the system calls that support the C library. Basically, they're just the POSIX versions with an '_' - prepended. This file lives in the `sys' directory so targets can provide - their own if desired (or they can put target dependant conditionals here). + prepended. Targets shall use to define their own + internal types if desired. + + There are three define patterns used for type definitions. Lets assume + xyz_t is a user type. + + The internal type definition uses __machine_xyz_t_defined. It is defined by + to disable a default definition in . It + must not be used in other files. + + User type definitions are guarded by __xyz_t_defined in glibc and + _XYZ_T_DECLARED in BSD compatible systems. */ #ifndef _SYS__TYPES_H #define _SYS__TYPES_H +#include +#include #include #include -#ifndef __off_t_defined +#ifndef __machine_blkcnt_t_defined +typedef long __blkcnt_t; +#endif + +#ifndef __machine_blksize_t_defined +typedef long __blksize_t; +#endif + +#ifndef __machine_fsblkcnt_t_defined +typedef __uint64_t __fsblkcnt_t; +#endif + +#ifndef __machine_fsfilcnt_t_defined +typedef __uint32_t __fsfilcnt_t; +#endif + +#ifndef __machine_off_t_defined typedef long _off_t; #endif -#ifndef __dev_t_defined +#if defined(__XMK__) +typedef signed char __pid_t; +#else +typedef int __pid_t; +#endif + +#ifndef __machine_dev_t_defined typedef short __dev_t; #endif -#ifndef __uid_t_defined +#ifndef __machine_uid_t_defined typedef unsigned short __uid_t; #endif -#ifndef __gid_t_defined +#ifndef __machine_gid_t_defined typedef unsigned short __gid_t; #endif -#ifndef __off64_t_defined +#ifndef __machine_id_t_defined +typedef __uint32_t __id_t; +#endif + +#ifndef __machine_ino_t_defined +#if (defined(__i386__) && (defined(GO32) || defined(__MSDOS__))) || \ + defined(__sparc__) || defined(__SPU__) +typedef unsigned long __ino_t; +#else +typedef unsigned short __ino_t; +#endif +#endif + +#ifndef __machine_mode_t_defined +#if defined(__i386__) && (defined(GO32) || defined(__MSDOS__)) +typedef int __mode_t; +#else +#if defined(__sparc__) && !defined(__sparc_v9__) +#ifdef __svr4__ +typedef unsigned long __mode_t; +#else +typedef unsigned short __mode_t; +#endif +#else +typedef __uint32_t __mode_t; +#endif +#endif +#endif + +#ifndef __machine_off64_t_defined __extension__ typedef long long _off64_t; #endif +#if defined(__CYGWIN__) && !defined(__LP64__) +typedef _off64_t __off_t; +#else +typedef _off_t __off_t; +#endif + +typedef _off64_t __loff_t; + +#ifndef __machine_key_t_defined +typedef long __key_t; +#endif + /* * We need fpos_t for the following, but it doesn't have a leading "_", * so we use _fpos_t instead. */ -#ifndef __fpos_t_defined +#ifndef __machine_fpos_t_defined typedef long _fpos_t; /* XXX must match off_t in */ /* (and must be `long' for now) */ #endif #ifdef __LARGE64_FILES -#ifndef __fpos64_t_defined +#ifndef __machine_fpos64_t_defined typedef _off64_t _fpos64_t; #endif #endif -#ifndef __ssize_t_defined +/* Defined by GCC provided */ +#undef __size_t + +#ifndef __machine_size_t_defined +#ifdef __SIZE_TYPE__ +typedef __SIZE_TYPE__ __size_t; +#else +#if defined(__INT_MAX__) && __INT_MAX__ == 2147483647 +typedef unsigned int __size_t; +#else +typedef unsigned long __size_t; +#endif +#endif +#endif + +#ifndef __machine_ssize_t_defined #ifdef __SIZE_TYPE__ /* If __SIZE_TYPE__ is defined (gcc) we define ssize_t based on size_t. We simply change "unsigned" to "signed" for this single definition @@ -63,10 +153,12 @@ typedef long _ssize_t; #endif #endif +typedef _ssize_t __ssize_t; + #define __need_wint_t #include -#ifndef __mbstate_t_defined +#ifndef __machine_mbstate_t_defined /* Conversion state information. */ typedef struct { @@ -79,13 +171,50 @@ typedef struct } _mbstate_t; #endif -#ifndef __flock_t_defined +#ifndef __machine_flock_t_defined typedef _LOCK_RECURSIVE_T _flock_t; #endif -#ifndef __iconv_t_defined +#ifndef __machine_iconv_t_defined /* Iconv descriptor type */ typedef void *_iconv_t; #endif +#ifndef __machine_clock_t_defined +#define _CLOCK_T_ unsigned long /* clock() */ +#endif + +typedef _CLOCK_T_ __clock_t; + +#if defined(_USE_LONG_TIME_T) || __LONG_MAX__ > 0x7fffffffL +#define _TIME_T_ long +#else +#define _TIME_T_ __int_least64_t +#endif +typedef _TIME_T_ __time_t; + +#define _CLOCKID_T_ unsigned long +typedef _CLOCKID_T_ __clockid_t; + +#define _TIMER_T_ unsigned long +typedef _TIMER_T_ __timer_t; + +#ifndef __machine_sa_family_t_defined +typedef __uint8_t __sa_family_t; +#endif + +#ifndef __machine_socklen_t_defined +typedef __uint32_t __socklen_t; +#endif + +typedef unsigned short __nlink_t; +typedef long __suseconds_t; /* microseconds (signed) */ +typedef unsigned long __useconds_t; /* microseconds (unsigned) */ + +#ifdef __GNUCLIKE_BUILTIN_VARARGS +typedef __builtin_va_list __va_list; +#else +typedef char * __va_list; +#endif /* __GNUCLIKE_BUILTIN_VARARGS */ + #endif /* _SYS__TYPES_H */ diff --git a/libc/xtensa-lx106-elf/include/sys/cdefs.h b/libc/xtensa-lx106-elf/include/sys/cdefs.h index a5e613c..8ce14b6 100644 --- a/libc/xtensa-lx106-elf/include/sys/cdefs.h +++ b/libc/xtensa-lx106-elf/include/sys/cdefs.h @@ -17,7 +17,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -69,7 +69,9 @@ /* * Testing against Clang-specific extensions. */ - +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif #ifndef __has_extension #define __has_extension __has_feature #endif @@ -100,33 +102,33 @@ #if defined(__GNUC__) || defined(__INTEL_COMPILER) #if __GNUC__ >= 3 || defined(__INTEL_COMPILER) -#define __GNUCLIKE_ASM 3 -#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS +#define __GNUCLIKE_ASM 3 +#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS #else -#define __GNUCLIKE_ASM 2 +#define __GNUCLIKE_ASM 2 #endif -#define __GNUCLIKE___TYPEOF 1 -#define __GNUCLIKE___OFFSETOF 1 -#define __GNUCLIKE___SECTION 1 +#define __GNUCLIKE___TYPEOF 1 +#define __GNUCLIKE___OFFSETOF 1 +#define __GNUCLIKE___SECTION 1 #ifndef __INTEL_COMPILER -# define __GNUCLIKE_CTOR_SECTION_HANDLING 1 +#define __GNUCLIKE_CTOR_SECTION_HANDLING 1 #endif -#define __GNUCLIKE_BUILTIN_CONSTANT_P 1 -# if defined(__INTEL_COMPILER) && defined(__cplusplus) \ - && __INTEL_COMPILER < 800 -# undef __GNUCLIKE_BUILTIN_CONSTANT_P -# endif +#define __GNUCLIKE_BUILTIN_CONSTANT_P 1 +#if defined(__INTEL_COMPILER) && defined(__cplusplus) && \ + __INTEL_COMPILER < 800 +#undef __GNUCLIKE_BUILTIN_CONSTANT_P +#endif -#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) && !defined(__INTEL_COMPILER) -# define __GNUCLIKE_BUILTIN_VARARGS 1 -# define __GNUCLIKE_BUILTIN_STDARG 1 -# define __GNUCLIKE_BUILTIN_VAALIST 1 +#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) +#define __GNUCLIKE_BUILTIN_VARARGS 1 +#define __GNUCLIKE_BUILTIN_STDARG 1 +#define __GNUCLIKE_BUILTIN_VAALIST 1 #endif #if defined(__GNUC__) -# define __GNUC_VA_LIST_COMPATIBILITY 1 +#define __GNUC_VA_LIST_COMPATIBILITY 1 #endif /* @@ -137,23 +139,23 @@ #endif #ifndef __INTEL_COMPILER -# define __GNUCLIKE_BUILTIN_NEXT_ARG 1 -# define __GNUCLIKE_MATH_BUILTIN_RELOPS +#define __GNUCLIKE_BUILTIN_NEXT_ARG 1 +#define __GNUCLIKE_MATH_BUILTIN_RELOPS #endif -#define __GNUCLIKE_BUILTIN_MEMCPY 1 +#define __GNUCLIKE_BUILTIN_MEMCPY 1 /* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */ -#define __CC_SUPPORTS_INLINE 1 -#define __CC_SUPPORTS___INLINE 1 -#define __CC_SUPPORTS___INLINE__ 1 +#define __CC_SUPPORTS_INLINE 1 +#define __CC_SUPPORTS___INLINE 1 +#define __CC_SUPPORTS___INLINE__ 1 -#define __CC_SUPPORTS___FUNC__ 1 -#define __CC_SUPPORTS_WARNING 1 +#define __CC_SUPPORTS___FUNC__ 1 +#define __CC_SUPPORTS_WARNING 1 -#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */ +#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */ -#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1 +#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1 #endif /* __GNUC__ || __INTEL_COMPILER */ @@ -229,8 +231,12 @@ #define __unused #define __packed #define __aligned(x) +#define __alloc_align(x) +#define __alloc_size(x) #define __section(x) +#define __weak_symbol #else +#define __weak_symbol __attribute__((__weak__)) #if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER) #define __dead2 #define __pure2 @@ -242,7 +248,7 @@ #define __unused /* XXX Find out what to do for __packed, __aligned and __section */ #endif -#if __GNUC_PREREQ__(2, 7) +#if __GNUC_PREREQ__(2, 7) || defined(__INTEL_COMPILER) #define __dead2 __attribute__((__noreturn__)) #define __pure2 __attribute__((__const__)) #define __unused __attribute__((__unused__)) @@ -251,16 +257,17 @@ #define __aligned(x) __attribute__((__aligned__(x))) #define __section(x) __attribute__((__section__(x))) #endif -#if defined(__INTEL_COMPILER) -#define __dead2 __attribute__((__noreturn__)) -#define __pure2 __attribute__((__const__)) -#define __unused __attribute__((__unused__)) -#define __used __attribute__((__used__)) -#define __packed __attribute__((__packed__)) -#define __aligned(x) __attribute__((__aligned__(x))) -#define __section(x) __attribute__((__section__(x))) +#if __GNUC_PREREQ__(4, 3) || __has_attribute(__alloc_size__) +#define __alloc_size(x) __attribute__((__alloc_size__(x))) +#else +#define __alloc_size(x) #endif +#if __GNUC_PREREQ__(4, 9) || __has_attribute(__alloc_align__) +#define __alloc_align(x) __attribute__((__alloc_align__(x))) +#else +#define __alloc_align(x) #endif +#endif /* lint */ #if !__GNUC_PREREQ__(2, 95) #define __alignof(x) __offsetof(struct { char __a; x __b; }, __b) @@ -270,7 +277,7 @@ * Keywords added in C11. */ -#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L || defined(lint) #if !__has_extension(c_alignas) #if (defined(__cplusplus) && __cplusplus >= 201103L) || \ @@ -288,7 +295,8 @@ #define _Alignof(x) __alignof(x) #endif -#if !__has_extension(c_atomic) && !__has_extension(cxx_atomic) +#if !defined(__cplusplus) && !__has_extension(c_atomic) && \ + !__has_extension(cxx_atomic) /* * No native support for _Atomic(). Place object in structure to prevent * most forms of direct non-atomic access. @@ -302,23 +310,28 @@ #define _Noreturn __dead2 #endif -#if __GNUC_PREREQ__(4, 6) && !defined(__cplusplus) -/* Do nothing: _Static_assert() works as per C11 */ -#elif !__has_extension(c_static_assert) +#if !__has_extension(c_static_assert) #if (defined(__cplusplus) && __cplusplus >= 201103L) || \ __has_extension(cxx_static_assert) #define _Static_assert(x, y) static_assert(x, y) +#elif __GNUC_PREREQ__(4,6) +/* Nothing, gcc 4.6 and higher has _Static_assert built-in */ #elif defined(__COUNTER__) #define _Static_assert(x, y) __Static_assert(x, __COUNTER__) #define __Static_assert(x, y) ___Static_assert(x, y) -#define ___Static_assert(x, y) typedef char __assert_ ## y[(x) ? 1 : -1] +#define ___Static_assert(x, y) typedef char __assert_ ## y[(x) ? 1 : -1] \ + __unused #else #define _Static_assert(x, y) struct __hack #endif #endif #if !__has_extension(c_thread_local) -/* XXX: Change this to test against C++11 when clang in base supports it. */ +/* + * XXX: Some compilers (Clang 3.3, GCC 4.7) falsely announce C++11 mode + * without actually supporting the thread_local keyword. Don't check for + * the presence of C++11 when defining _Thread_local. + */ #if /* (defined(__cplusplus) && __cplusplus >= 201103L) || */ \ __has_extension(cxx_thread_local) #define _Thread_local thread_local @@ -338,7 +351,8 @@ * distinguish multiple cases. */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ + __has_extension(c_generic_selections) #define __generic(expr, t, yes, no) \ _Generic(expr, t: yes, default: no) #elif __GNUC_PREREQ__(3, 1) && !defined(__cplusplus) @@ -347,6 +361,21 @@ __builtin_types_compatible_p(__typeof(expr), t), yes, no) #endif +/* + * C99 Static array indices in function parameter declarations. Syntax such as: + * void bar(int myArray[static 10]); + * is allowed in C99 but not in C++. Define __min_size appropriately so + * headers using it can be compiled in either language. Use like this: + * void bar(int myArray[__min_size(10)]); + */ +#if !defined(__cplusplus) && \ + (defined(__clang__) || __GNUC_PREREQ__(4, 6)) && \ + (!defined(__STDC_VERSION__) || (__STDC_VERSION__ >= 199901)) +#define __min_size(x) static (x) +#else +#define __min_size(x) (x) +#endif + #if __GNUC_PREREQ__(2, 96) #define __malloc_like __attribute__((__malloc__)) #define __pure __attribute__((__pure__)) @@ -368,15 +397,19 @@ #endif #if __GNUC_PREREQ__(3, 3) -#define __nonnull(x) __attribute__((__nonnull__(x))) +#define __nonnull(x) __attribute__((__nonnull__(x))) +#define __nonnull_all __attribute__((__nonnull__)) #else -#define __nonnull(x) +#define __nonnull(x) +#define __nonnull_all #endif #if __GNUC_PREREQ__(3, 4) #define __fastcall __attribute__((__fastcall__)) +#define __result_use_check __attribute__((__warn_unused_result__)) #else #define __fastcall +#define __result_use_check #endif #if __GNUC_PREREQ__(4, 1) @@ -385,6 +418,12 @@ #define __returns_twice #endif +#if __GNUC_PREREQ__(4, 6) || __has_builtin(__builtin_unreachable) +#define __unreachable() __builtin_unreachable() +#else +#define __unreachable() ((void)0) +#endif + /* XXX: should use `#if __STDC_VERSION__ < 199901'. */ #if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) #define __func__ NULL @@ -433,19 +472,26 @@ * larger code. */ #if __GNUC_PREREQ__(2, 96) -#define __predict_true(exp) __builtin_expect((exp), 1) -#define __predict_false(exp) __builtin_expect((exp), 0) +#define __predict_true(exp) __builtin_expect((exp), 1) +#define __predict_false(exp) __builtin_expect((exp), 0) #else -#define __predict_true(exp) (exp) -#define __predict_false(exp) (exp) +#define __predict_true(exp) (exp) +#define __predict_false(exp) (exp) #endif -#if __GNUC_PREREQ__(4, 2) -#define __hidden __attribute__((__visibility__("hidden"))) +#if __GNUC_PREREQ__(4, 0) +#define __null_sentinel __attribute__((__sentinel__)) #define __exported __attribute__((__visibility__("default"))) +/* Only default visibility is supported on PE/COFF targets. */ +#ifndef __CYGWIN__ +#define __hidden __attribute__((__visibility__("hidden"))) #else #define __hidden +#endif +#else +#define __null_sentinel #define __exported +#define __hidden #endif #define __offsetof(type, field) offsetof(type, field) @@ -460,7 +506,7 @@ */ #if __GNUC_PREREQ__(3, 1) #define __containerof(x, s, m) ({ \ - const volatile __typeof__(((s *)0)->m) *__x = (x); \ + const volatile __typeof(((s *)0)->m) *__x = (x); \ __DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m));\ }) #else @@ -583,128 +629,96 @@ #define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var)) #endif -/*- - * The following definitions are an extension of the behavior originally - * implemented in , but with a different level of granularity. - * POSIX.1 requires that the macros we test be defined before any standard - * header file is included. - * - * Here's a quick run-down of the versions: - * defined(_POSIX_SOURCE) 1003.1-1988 - * _POSIX_C_SOURCE == 1 1003.1-1990 - * _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option - * _POSIX_C_SOURCE == 199309 1003.1b-1993 - * _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995, - * and the omnibus ISO/IEC 9945-1: 1996 - * _POSIX_C_SOURCE == 200112 1003.1-2001 - * _POSIX_C_SOURCE == 200809 1003.1-2008 - * - * In addition, the X/Open Portability Guide, which is now the Single UNIX - * Specification, defines a feature-test macro which indicates the version of - * that specification, and which subsumes _POSIX_C_SOURCE. - * - * Our macros begin with two underscores to avoid namespace screwage. +/* + * Nullability qualifiers: currently only supported by Clang. */ - -/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1 -#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */ -#define _POSIX_C_SOURCE 199009 -#endif - -/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199209 -#endif - -/* Deal with various X/Open Portability Guides and Single UNIX Spec. */ -#ifdef _XOPEN_SOURCE -#if _XOPEN_SOURCE - 0 >= 700 -#define __XSI_VISIBLE 700 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200809 -#elif _XOPEN_SOURCE - 0 >= 600 -#define __XSI_VISIBLE 600 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112 -#elif _XOPEN_SOURCE - 0 >= 500 -#define __XSI_VISIBLE 500 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199506 -#endif +#if !(defined(__clang__) && __has_feature(nullability)) +#define _Nonnull +#define _Nullable +#define _Null_unspecified +#define __NULLABILITY_PRAGMA_PUSH +#define __NULLABILITY_PRAGMA_POP +#else +#define __NULLABILITY_PRAGMA_PUSH _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wnullability-completeness\"") +#define __NULLABILITY_PRAGMA_POP _Pragma("clang diagnostic pop") #endif /* - * Deal with all versions of POSIX. The ordering relative to the tests above is - * important. - */ -#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 198808 -#endif -#ifdef _POSIX_C_SOURCE -#if _POSIX_C_SOURCE >= 200809 -#define __POSIX_VISIBLE 200809 -#define __ISO_C_VISIBLE 1999 -#elif _POSIX_C_SOURCE >= 200112 -#define __POSIX_VISIBLE 200112 -#define __ISO_C_VISIBLE 1999 -#elif _POSIX_C_SOURCE >= 199506 -#define __POSIX_VISIBLE 199506 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199309 -#define __POSIX_VISIBLE 199309 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199209 -#define __POSIX_VISIBLE 199209 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199009 -#define __POSIX_VISIBLE 199009 -#define __ISO_C_VISIBLE 1990 -#else -#define __POSIX_VISIBLE 198808 -#define __ISO_C_VISIBLE 0 -#endif /* _POSIX_C_SOURCE */ -#else -/*- - * Deal with _ANSI_SOURCE: - * If it is defined, and no other compilation environment is explicitly - * requested, then define our internal feature-test macros to zero. This - * makes no difference to the preprocessor (undefined symbols in preprocessing - * expressions are defined to have value zero), but makes it more convenient for - * a test program to print out the values. + * Type Safety Checking * - * If a program mistakenly defines _ANSI_SOURCE and some other macro such as - * _POSIX_C_SOURCE, we will assume that it wants the broader compilation - * environment (and in fact we will never get here). + * Clang provides additional attributes to enable checking type safety + * properties that cannot be enforced by the C type system. */ -#if defined(_ANSI_SOURCE) /* Hide almost everything. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 1990 -#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 1999 -#elif defined(_C11_SOURCE) /* Localism to specify strict C11 env. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 2011 -#elif defined(_GNU_SOURCE) /* Everything and the kitchen sink. */ -#define __POSIX_VISIBLE 200809 -#define __XSI_VISIBLE 700 -#define __BSD_VISIBLE 1 -#define __ISO_C_VISIBLE 2011 -#define __GNU_VISIBLE 1 -#else /* Default: everything except __GNU_VISIBLE. */ -#define __POSIX_VISIBLE 200809 -#define __XSI_VISIBLE 700 -#define __BSD_VISIBLE 1 -#define __ISO_C_VISIBLE 2011 -#endif + +#if __has_attribute(__argument_with_type_tag__) && \ + __has_attribute(__type_tag_for_datatype__) && !defined(lint) +#define __arg_type_tag(arg_kind, arg_idx, type_tag_idx) \ + __attribute__((__argument_with_type_tag__(arg_kind, arg_idx, type_tag_idx))) +#define __datatype_type_tag(kind, type) \ + __attribute__((__type_tag_for_datatype__(kind, type))) +#else +#define __arg_type_tag(arg_kind, arg_idx, type_tag_idx) +#define __datatype_type_tag(kind, type) #endif +/* + * Lock annotations. + * + * Clang provides support for doing basic thread-safety tests at + * compile-time, by marking which locks will/should be held when + * entering/leaving a functions. + * + * Furthermore, it is also possible to annotate variables and structure + * members to enforce that they are only accessed when certain locks are + * held. + */ + +#if __has_extension(c_thread_safety_attributes) +#define __lock_annotate(x) __attribute__((x)) +#else +#define __lock_annotate(x) +#endif + +/* Structure implements a lock. */ +/* FIXME: Use __lockable__, etc. to avoid colliding with user namespace macros, + * once clang is fixed: https://bugs.llvm.org/show_bug.cgi?id=34319 */ +#define __lockable __lock_annotate(lockable) + +/* Function acquires an exclusive or shared lock. */ +#define __locks_exclusive(...) \ + __lock_annotate(exclusive_lock_function(__VA_ARGS__)) +#define __locks_shared(...) \ + __lock_annotate(shared_lock_function(__VA_ARGS__)) + +/* Function attempts to acquire an exclusive or shared lock. */ +#define __trylocks_exclusive(...) \ + __lock_annotate(exclusive_trylock_function(__VA_ARGS__)) +#define __trylocks_shared(...) \ + __lock_annotate(shared_trylock_function(__VA_ARGS__)) + +/* Function releases a lock. */ +#define __unlocks(...) __lock_annotate(unlock_function(__VA_ARGS__)) + +/* Function asserts that an exclusive or shared lock is held. */ +#define __asserts_exclusive(...) \ + __lock_annotate(assert_exclusive_lock(__VA_ARGS__)) +#define __asserts_shared(...) \ + __lock_annotate(assert_shared_lock(__VA_ARGS__)) + +/* Function requires that an exclusive or shared lock is or is not held. */ +#define __requires_exclusive(...) \ + __lock_annotate(exclusive_locks_required(__VA_ARGS__)) +#define __requires_shared(...) \ + __lock_annotate(shared_locks_required(__VA_ARGS__)) +#define __requires_unlocked(...) \ + __lock_annotate(locks_excluded(__VA_ARGS__)) + +/* Function should not be analyzed. */ +#define __no_lock_analysis __lock_annotate(no_thread_safety_analysis) + +/* Guard variables and structure members by lock. */ +#define __guarded_by(x) __lock_annotate(guarded_by(x)) +#define __pt_guarded_by(x) __lock_annotate(pt_guarded_by(x)) + #endif /* !_SYS_CDEFS_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/config.h b/libc/xtensa-lx106-elf/include/sys/config.h index f6f923e..3c185ea 100644 --- a/libc/xtensa-lx106-elf/include/sys/config.h +++ b/libc/xtensa-lx106-elf/include/sys/config.h @@ -75,7 +75,7 @@ #define _POINTER_INT short #endif -#if defined(__m68k__) || defined(__mc68000__) +#if defined(__m68k__) || defined(__mc68000__) || defined(__riscv) #define _READ_WRITE_RETURN_TYPE _ssize_t #endif @@ -92,7 +92,6 @@ /* we want the reentrancy structure to be returned by a function */ #define __DYNAMIC_REENT__ #define HAVE_GETDATE -#define _HAVE_SYSTYPES #define _READ_WRITE_RETURN_TYPE _ssize_t #define __LARGE64_FILES 1 /* we use some glibc header files so turn on glibc large file feature */ @@ -155,6 +154,7 @@ #define _REENT_SMALL #endif +#define __BUFSIZ__ 256 #define __SMALL_BITFIELDS #ifdef __MSP430X_LARGE__ @@ -185,6 +185,10 @@ #define __CUSTOM_FILE_IO__ #endif +#if defined(__or1k__) || defined(__or1knd__) +#define __DYNAMIC_REENT__ +#endif + #ifdef __XTENSA__ #include #define MALLOC_ALIGNMENT ((XCHAL_DATA_WIDTH) < 16 ? 16 : (XCHAL_DATA_WIDTH)) @@ -235,9 +239,6 @@ #if defined(__CYGWIN__) #include -#if !defined (__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) -#define __USE_XOPEN2K 1 -#endif #endif #if defined(__rtems__) @@ -245,6 +246,7 @@ #define _READ_WRITE_RETURN_TYPE _ssize_t #define __DYNAMIC_REENT__ #define _REENT_GLOBAL_ATEXIT +#define _REENT_GLOBAL_STDIO_STREAMS #endif #ifndef __EXPORT @@ -282,6 +284,18 @@ #endif #endif +#ifdef _WANT_REENT_GLOBAL_STDIO_STREAMS +#ifndef _REENT_GLOBAL_STDIO_STREAMS +#define _REENT_GLOBAL_STDIO_STREAMS +#endif +#endif + +#ifdef _WANT_USE_LONG_TIME_T +#ifndef _USE_LONG_TIME_T +#define _USE_LONG_TIME_T +#endif +#endif + /* If _MB_EXTENDED_CHARSETS_ALL is set, we want all of the extended charsets. The extended charsets add a few functions and a couple of tables of a few K each. */ diff --git a/libc/xtensa-lx106-elf/include/sys/features.h b/libc/xtensa-lx106-elf/include/sys/features.h index 1d90921..c9133af 100644 --- a/libc/xtensa-lx106-elf/include/sys/features.h +++ b/libc/xtensa-lx106-elf/include/sys/features.h @@ -1,7 +1,7 @@ /* * Written by Joel Sherrill . * - * COPYRIGHT (c) 1989-2000. + * COPYRIGHT (c) 1989-2014. * * On-Line Applications Research Corporation (OAR). * @@ -25,11 +25,7 @@ extern "C" { #endif -/* Macros to determine that newlib is being used. Put in this header to - * be similar to where glibc stores its version of these macros. - */ -#define __NEWLIB__ 2 -#define __NEWLIB_MINOR__ 1 +#include <_newlib_version.h> /* Macro to test version of GCC. Returns 0 for non-GCC or too old GCC. */ #ifndef __GNUC_PREREQ @@ -43,6 +39,281 @@ extern "C" { /* Version with trailing underscores for BSD compatibility. */ #define __GNUC_PREREQ__(ma, mi) __GNUC_PREREQ(ma, mi) + +/* + * Feature test macros control which symbols are exposed by the system + * headers. Any of these must be defined before including any headers. + * + * __STRICT_ANSI__ (defined by gcc -ansi, -std=c90, -std=c99, or -std=c11) + * ISO C + * + * _POSIX_SOURCE (deprecated by _POSIX_C_SOURCE=1) + * _POSIX_C_SOURCE >= 1 + * POSIX.1-1990 + * + * _POSIX_C_SOURCE >= 2 + * POSIX.2-1992 + * + * _POSIX_C_SOURCE >= 199309L + * POSIX.1b-1993 Real-time extensions + * + * _POSIX_C_SOURCE >= 199506L + * POSIX.1c-1995 Threads extensions + * + * _POSIX_C_SOURCE >= 200112L + * POSIX.1-2001 and C99 + * + * _POSIX_C_SOURCE >= 200809L + * POSIX.1-2008 + * + * _XOPEN_SOURCE + * POSIX.1-1990 and XPG4 + * + * _XOPEN_SOURCE_EXTENDED + * SUSv1 (POSIX.2-1992 plus XPG4v2) + * + * _XOPEN_SOURCE >= 500 + * SUSv2 (POSIX.1c-1995 plus XSI) + * + * _XOPEN_SOURCE >= 600 + * SUSv3 (POSIX.1-2001 plus XSI) and C99 + * + * _XOPEN_SOURCE >= 700 + * SUSv4 (POSIX.1-2008 plus XSI) + * + * _ISOC99_SOURCE or gcc -std=c99 or g++ + * ISO C99 + * + * _ISOC11_SOURCE or gcc -std=c11 or g++ -std=c++11 + * ISO C11 + * + * _ATFILE_SOURCE (implied by _POSIX_C_SOURCE >= 200809L) + * "at" functions + * + * _LARGEFILE_SOURCE (deprecated by _XOPEN_SOURCE >= 500) + * fseeko, ftello + * + * _GNU_SOURCE + * All of the above plus GNU extensions + * + * _BSD_SOURCE (deprecated by _DEFAULT_SOURCE) + * _SVID_SOURCE (deprecated by _DEFAULT_SOURCE) + * _DEFAULT_SOURCE (or none of the above) + * POSIX-1.2008 with BSD and SVr4 extensions + */ + +#ifdef _GNU_SOURCE +#undef _ATFILE_SOURCE +#define _ATFILE_SOURCE 1 +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE 1 +#undef _ISOC99_SOURCE +#define _ISOC99_SOURCE 1 +#undef _ISOC11_SOURCE +#define _ISOC11_SOURCE 1 +#undef _POSIX_SOURCE +#define _POSIX_SOURCE 1 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L +#undef _XOPEN_SOURCE +#define _XOPEN_SOURCE 700 +#undef _XOPEN_SOURCE_EXTENDED +#define _XOPEN_SOURCE_EXTENDED 1 +#endif /* _GNU_SOURCE */ + +#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || \ + (!defined(__STRICT_ANSI__) && !defined(_ANSI_SOURCE) && \ + !defined(_ISOC99_SOURCE) && !defined(_POSIX_SOURCE) && \ + !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) +#undef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE 1 +#endif + +#if defined(_DEFAULT_SOURCE) +#undef _POSIX_SOURCE +#define _POSIX_SOURCE 1 +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) && \ + ((!defined(__STRICT_ANSI__) && !defined(_ANSI_SOURCE)) || \ + (_XOPEN_SOURCE - 0) >= 500) +#define _POSIX_SOURCE 1 +#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0) >= 700 +#define _POSIX_C_SOURCE 200809L +#elif (_XOPEN_SOURCE - 0) >= 600 +#define _POSIX_C_SOURCE 200112L +#elif (_XOPEN_SOURCE - 0) >= 500 +#define _POSIX_C_SOURCE 199506L +#elif (_XOPEN_SOURCE - 0) < 500 +#define _POSIX_C_SOURCE 2 +#endif +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809 +#undef _ATFILE_SOURCE +#define _ATFILE_SOURCE 1 +#endif + +/* + * The following private macros are used throughout the headers to control + * which symbols should be exposed. They are for internal use only, as + * indicated by the leading double underscore, and must never be used outside + * of these headers. + * + * __POSIX_VISIBLE + * any version of POSIX.1; enabled by default, or with _POSIX_SOURCE, + * any value of _POSIX_C_SOURCE, or _XOPEN_SOURCE >= 500. + * + * __POSIX_VISIBLE >= 2 + * POSIX.2-1992; enabled by default, with _POSIX_C_SOURCE >= 2, + * or _XOPEN_SOURCE >= 500. + * + * __POSIX_VISIBLE >= 199309 + * POSIX.1b-1993; enabled by default, with _POSIX_C_SOURCE >= 199309L, + * or _XOPEN_SOURCE >= 500. + * + * __POSIX_VISIBLE >= 199506 + * POSIX.1c-1995; enabled by default, with _POSIX_C_SOURCE >= 199506L, + * or _XOPEN_SOURCE >= 500. + * + * __POSIX_VISIBLE >= 200112 + * POSIX.1-2001; enabled by default, with _POSIX_C_SOURCE >= 200112L, + * or _XOPEN_SOURCE >= 600. + * + * __POSIX_VISIBLE >= 200809 + * POSIX.1-2008; enabled by default, with _POSIX_C_SOURCE >= 200809L, + * or _XOPEN_SOURCE >= 700. + * + * __XSI_VISIBLE + * XPG4 XSI extensions; enabled with any version of _XOPEN_SOURCE. + * + * __XSI_VISIBLE >= 4 + * SUSv1 XSI extensions; enabled with both _XOPEN_SOURCE and + * _XOPEN_SOURCE_EXTENDED together. + * + * __XSI_VISIBLE >= 500 + * SUSv2 XSI extensions; enabled with _XOPEN_SOURCE >= 500. + * + * __XSI_VISIBLE >= 600 + * SUSv3 XSI extensions; enabled with _XOPEN_SOURCE >= 600. + * + * __XSI_VISIBLE >= 700 + * SUSv4 XSI extensions; enabled with _XOPEN_SOURCE >= 700. + * + * __ISO_C_VISIBLE >= 1999 + * ISO C99; enabled with gcc -std=c99 or newer (on by default since GCC 5), + * any version of C++, or with _ISOC99_SOURCE, _POSIX_C_SOURCE >= 200112L, + * or _XOPEN_SOURCE >= 600. + * + * __ISO_C_VISIBLE >= 2011 + * ISO C11; enabled with gcc -std=c11 or newer (on by default since GCC 5), + * g++ -std=c++11 or newer (on by default since GCC 6), or with + * _ISOC11_SOURCE. + * + * __ATFILE_VISIBLE + * "at" functions; enabled by default, with _ATFILE_SOURCE, + * _POSIX_C_SOURCE >= 200809L, or _XOPEN_SOURCE >= 700. + * + * __LARGEFILE_VISIBLE + * fseeko, ftello; enabled with _LARGEFILE_SOURCE or _XOPEN_SOURCE >= 500. + * + * __BSD_VISIBLE + * BSD extensions; enabled by default, or with _BSD_SOURCE. + * + * __SVID_VISIBLE + * SVr4 extensions; enabled by default, or with _SVID_SOURCE. + * + * __MISC_VISIBLE + * Extensions found in both BSD and SVr4 (shorthand for + * (__BSD_VISIBLE || __SVID_VISIBLE)), or newlib-specific + * extensions; enabled by default. + * + * __GNU_VISIBLE + * GNU extensions; enabled with _GNU_SOURCE. + * + * In all cases above, "enabled by default" means either by defining + * _DEFAULT_SOURCE, or by not defining any of the public feature test macros. + * Defining _GNU_SOURCE makes all of the above avaliable. + */ + +#ifdef _ATFILE_SOURCE +#define __ATFILE_VISIBLE 1 +#else +#define __ATFILE_VISIBLE 0 +#endif + +#ifdef _DEFAULT_SOURCE +#define __BSD_VISIBLE 1 +#else +#define __BSD_VISIBLE 0 +#endif + +#ifdef _GNU_SOURCE +#define __GNU_VISIBLE 1 +#else +#define __GNU_VISIBLE 0 +#endif + +#if defined(_ISOC11_SOURCE) || \ + (__STDC_VERSION__ - 0) >= 201112L || (__cplusplus - 0) >= 201103L +#define __ISO_C_VISIBLE 2011 +#elif defined(_ISOC99_SOURCE) || (_POSIX_C_SOURCE - 0) >= 200112L || \ + (__STDC_VERSION__ - 0) >= 199901L || defined(__cplusplus) +#define __ISO_C_VISIBLE 1999 +#else +#define __ISO_C_VISIBLE 1990 +#endif + +#if defined(_LARGEFILE_SOURCE) || (_XOPEN_SOURCE - 0) >= 500 +#define __LARGEFILE_VISIBLE 1 +#else +#define __LARGEFILE_VISIBLE 0 +#endif + +#ifdef _DEFAULT_SOURCE +#define __MISC_VISIBLE 1 +#else +#define __MISC_VISIBLE 0 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 200809L +#define __POSIX_VISIBLE 200809 +#elif (_POSIX_C_SOURCE - 0) >= 200112L +#define __POSIX_VISIBLE 200112 +#elif (_POSIX_C_SOURCE - 0) >= 199506L +#define __POSIX_VISIBLE 199506 +#elif (_POSIX_C_SOURCE - 0) >= 199309L +#define __POSIX_VISIBLE 199309 +#elif (_POSIX_C_SOURCE - 0) >= 2 || defined(_XOPEN_SOURCE) +#define __POSIX_VISIBLE 199209 +#elif defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) +#define __POSIX_VISIBLE 199009 +#else +#define __POSIX_VISIBLE 0 +#endif + +#ifdef _DEFAULT_SOURCE +#define __SVID_VISIBLE 1 +#else +#define __SVID_VISIBLE 0 +#endif + +#if (_XOPEN_SOURCE - 0) >= 700 +#define __XSI_VISIBLE 700 +#elif (_XOPEN_SOURCE - 0) >= 600 +#define __XSI_VISIBLE 600 +#elif (_XOPEN_SOURCE - 0) >= 500 +#define __XSI_VISIBLE 500 +#elif defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED) +#define __XSI_VISIBLE 4 +#elif defined(_XOPEN_SOURCE) +#define __XSI_VISIBLE 1 +#else +#define __XSI_VISIBLE 0 +#endif + /* RTEMS adheres to POSIX -- 1003.1b with some features from annexes. */ #ifdef __rtems__ @@ -57,11 +328,12 @@ extern "C" { #define _POSIX_MEMORY_PROTECTION 1 #define _POSIX_MESSAGE_PASSING 1 #define _POSIX_MONOTONIC_CLOCK 200112L +#define _POSIX_CLOCK_SELECTION 200112L #define _POSIX_PRIORITIZED_IO 1 #define _POSIX_PRIORITY_SCHEDULING 1 #define _POSIX_REALTIME_SIGNALS 1 #define _POSIX_SEMAPHORES 1 -/* #define _POSIX_SHARED_MEMORY_OBJECTS 1 */ +#define _POSIX_SHARED_MEMORY_OBJECTS 1 #define _POSIX_SYNCHRONIZED_IO 1 #define _POSIX_TIMERS 1 #define _POSIX_BARRIERS 200112L @@ -94,6 +366,9 @@ extern "C" { /* UNIX98 added some new pthread mutex attributes */ #define _UNIX98_THREAD_MUTEX_ATTRIBUTES 1 +/* POSIX 1003.26-2003 defined device control method */ +#define _POSIX_26_VERSION 200312L + #endif /* XMK loosely adheres to POSIX -- 1003.1 */ @@ -111,62 +386,82 @@ extern "C" { #ifdef __CYGWIN__ -#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || __STDC_VERSION__ >= 199901L +#if __POSIX_VISIBLE >= 200809 +#define _POSIX_VERSION 200809L +#define _POSIX2_VERSION 200809L +#elif __POSIX_VISIBLE >= 200112 #define _POSIX_VERSION 200112L #define _POSIX2_VERSION 200112L -#define _XOPEN_VERSION 600 +#elif __POSIX_VISIBLE >= 199506 +#define _POSIX_VERSION 199506L +#define _POSIX2_VERSION 199506L +#elif __POSIX_VISIBLE >= 199309 +#define _POSIX_VERSION 199309L +#define _POSIX2_VERSION 199209L +#elif __POSIX_VISIBLE >= 199209 +#define _POSIX_VERSION 199009L +#define _POSIX2_VERSION 199209L +#elif __POSIX_VISIBLE +#define _POSIX_VERSION 199009L +#endif +#if __XSI_VISIBLE >= 4 +#define _XOPEN_VERSION __XSI_VISIBLE +#endif -#define _POSIX_ADVISORY_INFO 200112L +#define _POSIX_ADVISORY_INFO 200809L /* #define _POSIX_ASYNCHRONOUS_IO -1 */ -/* #define _POSIX_BARRIERS -1 */ +#define _POSIX_BARRIERS 200809L #define _POSIX_CHOWN_RESTRICTED 1 -#define _POSIX_CLOCK_SELECTION 200112L -#define _POSIX_CPUTIME 200112L -#define _POSIX_FSYNC 200112L -#define _POSIX_IPV6 200112L +#define _POSIX_CLOCK_SELECTION 200809L +#define _POSIX_CPUTIME 200809L +#define _POSIX_FSYNC 200809L +#define _POSIX_IPV6 200809L #define _POSIX_JOB_CONTROL 1 -#define _POSIX_MAPPED_FILES 200112L +#define _POSIX_MAPPED_FILES 200809L /* #define _POSIX_MEMLOCK -1 */ -#define _POSIX_MEMLOCK_RANGE 200112L -#define _POSIX_MEMORY_PROTECTION 200112L -#define _POSIX_MESSAGE_PASSING 200112L -#define _POSIX_MONOTONIC_CLOCK 200112L +#define _POSIX_MEMLOCK_RANGE 200809L +#define _POSIX_MEMORY_PROTECTION 200809L +#define _POSIX_MESSAGE_PASSING 200809L +#define _POSIX_MONOTONIC_CLOCK 200809L #define _POSIX_NO_TRUNC 1 /* #define _POSIX_PRIORITIZED_IO -1 */ -#define _POSIX_PRIORITY_SCHEDULING 200112L -#define _POSIX_RAW_SOCKETS 200112L -#define _POSIX_READER_WRITER_LOCKS 200112L -#define _POSIX_REALTIME_SIGNALS 200112L +#define _POSIX_PRIORITY_SCHEDULING 200809L +#define _POSIX_RAW_SOCKETS 200809L +#define _POSIX_READER_WRITER_LOCKS 200809L +#define _POSIX_REALTIME_SIGNALS 200809L #define _POSIX_REGEXP 1 #define _POSIX_SAVED_IDS 1 -#define _POSIX_SEMAPHORES 200112L -#define _POSIX_SHARED_MEMORY_OBJECTS 200112L +#define _POSIX_SEMAPHORES 200809L +#define _POSIX_SHARED_MEMORY_OBJECTS 200809L #define _POSIX_SHELL 1 -/* #define _POSIX_SPAWN -1 */ -#define _POSIX_SPIN_LOCKS 200112L +#define _POSIX_SPAWN 200809L +#define _POSIX_SPIN_LOCKS 200809L /* #define _POSIX_SPORADIC_SERVER -1 */ -#define _POSIX_SYNCHRONIZED_IO 200112L -#define _POSIX_THREAD_ATTR_STACKADDR 200112L -#define _POSIX_THREAD_ATTR_STACKSIZE 200112L -#define _POSIX_THREAD_CPUTIME 200112L +#define _POSIX_SYNCHRONIZED_IO 200809L +#define _POSIX_THREAD_ATTR_STACKADDR 200809L +#define _POSIX_THREAD_ATTR_STACKSIZE 200809L +#define _POSIX_THREAD_CPUTIME 200809L /* #define _POSIX_THREAD_PRIO_INHERIT -1 */ /* #define _POSIX_THREAD_PRIO_PROTECT -1 */ -#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L -#define _POSIX_THREAD_PROCESS_SHARED 200112L -#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200809L +#define _POSIX_THREAD_PROCESS_SHARED 200809L +#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L /* #define _POSIX_THREAD_SPORADIC_SERVER -1 */ -#define _POSIX_THREADS 200112L +#define _POSIX_THREADS 200809L /* #define _POSIX_TIMEOUTS -1 */ -#define _POSIX_TIMERS 1 +#define _POSIX_TIMERS 200809L /* #define _POSIX_TRACE -1 */ /* #define _POSIX_TRACE_EVENT_FILTER -1 */ /* #define _POSIX_TRACE_INHERIT -1 */ /* #define _POSIX_TRACE_LOG -1 */ /* #define _POSIX_TYPED_MEMORY_OBJECTS -1 */ #define _POSIX_VDISABLE '\0' -#define _POSIX2_C_BIND 200112L -#define _POSIX2_C_DEV 200112L -#define _POSIX2_CHAR_TERM 200112L + +#if __POSIX_VISIBLE >= 2 +#define _POSIX2_C_VERSION _POSIX2_VERSION +#define _POSIX2_C_BIND _POSIX2_VERSION +#define _POSIX2_C_DEV _POSIX2_VERSION +#define _POSIX2_CHAR_TERM _POSIX2_VERSION /* #define _POSIX2_FORT_DEV -1 */ /* #define _POSIX2_FORT_RUN -1 */ /* #define _POSIX2_LOCALEDEF -1 */ @@ -176,8 +471,10 @@ extern "C" { /* #define _POSIX2_PBS_LOCATE -1 */ /* #define _POSIX2_PBS_MESSAGE -1 */ /* #define _POSIX2_PBS_TRACK -1 */ -#define _POSIX2_SW_DEV 200112L -#define _POSIX2_UPE 200112L +#define _POSIX2_SW_DEV _POSIX2_VERSION +#define _POSIX2_UPE _POSIX2_VERSION +#endif /* __POSIX_VISIBLE >= 2 */ + #define _POSIX_V6_ILP32_OFF32 -1 #ifdef __LP64__ #define _POSIX_V6_ILP32_OFFBIG -1 @@ -188,10 +485,16 @@ extern "C" { #define _POSIX_V6_LP64_OFF64 -1 #define _POSIX_V6_LPBIG_OFFBIG -1 #endif +#define _POSIX_V7_ILP32_OFF32 _POSIX_V6_ILP32_OFF32 +#define _POSIX_V7_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG +#define _POSIX_V7_LP64_OFF64 _POSIX_V6_LP64_OFF64 +#define _POSIX_V7_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG #define _XBS5_ILP32_OFF32 _POSIX_V6_ILP32_OFF32 #define _XBS5_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG #define _XBS5_LP64_OFF64 _POSIX_V6_LP64_OFF64 #define _XBS5_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG + +#if __XSI_VISIBLE #define _XOPEN_CRYPT 1 #define _XOPEN_ENH_I18N 1 /* #define _XOPEN_LEGACY -1 */ @@ -200,35 +503,14 @@ extern "C" { #define _XOPEN_SHM 1 /* #define _XOPEN_STREAMS -1 */ /* #define _XOPEN_UNIX -1 */ +#endif /* __XSI_VISIBLE */ -#endif /* !__STRICT_ANSI__ || __cplusplus || __STDC_VERSION__ >= 199901L */ - -/* The value corresponds to UNICODE version 4.0, which is the version - supported by XP. Newlib supports 5.2 (2011) but so far Cygwin needs - the MS conversions for double-byte charsets. */ -#define __STDC_ISO_10646__ 200305L +/* The value corresponds to UNICODE version 5.2, which is the current + state of newlib's wide char conversion functions. */ +#define __STDC_ISO_10646__ 200910L #endif /* __CYGWIN__ */ -/* Per the permission given in POSIX.1-2008 section 2.2.1, define - * _POSIX_C_SOURCE if _XOPEN_SOURCE is defined and _POSIX_C_SOURCE is not. - * (_XOPEN_SOURCE indicates that XSI extensions are desired by an application.) - * This permission is first granted in 2008, but use it for older ones, also. - * Allow for _XOPEN_SOURCE to be empty (from the earliest form of it, before it - * was required to have specific values). - */ -#if !defined(_POSIX_C_SOURCE) && defined(_XOPEN_SOURCE) - #if (_XOPEN_SOURCE - 0) == 700 /* POSIX.1-2008 */ - #define _POSIX_C_SOURCE 200809L - #elif (_XOPEN_SOURCE - 0) == 600 /* POSIX.1-2001 or 2004 */ - #define _POSIX_C_SOURCE 200112L - #elif (_XOPEN_SOURCE - 0) == 500 /* POSIX.1-1995 */ - #define _POSIX_C_SOURCE 199506L - #elif (_XOPEN_SOURCE - 0) < 500 /* really old */ - #define _POSIX_C_SOURCE 2 - #endif -#endif - #ifdef __cplusplus } #endif diff --git a/libc/xtensa-lx106-elf/include/sys/param.h b/libc/xtensa-lx106-elf/include/sys/param.h index ef203d3..9a6f115 100644 --- a/libc/xtensa-lx106-elf/include/sys/param.h +++ b/libc/xtensa-lx106-elf/include/sys/param.h @@ -10,6 +10,9 @@ #include #include +#ifndef NBBY +# define NBBY 8 /* number of bits in a byte */ +#endif #ifndef HZ # define HZ (60) #endif @@ -25,4 +28,8 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) +#endif + #endif diff --git a/libc/xtensa-lx106-elf/include/sys/queue.h b/libc/xtensa-lx106-elf/include/sys/queue.h index 4bc7dac..491bdde 100644 --- a/libc/xtensa-lx106-elf/include/sys/queue.h +++ b/libc/xtensa-lx106-elf/include/sys/queue.h @@ -10,7 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -76,11 +76,17 @@ * * For details on the use of these macros, see the queue(3) manual page. * + * Below is a summary of implemented functions where: + * + means the macro is available + * - means the macro is not available + * s means the macro is available but is slow (runs in O(n) time) * * SLIST LIST STAILQ TAILQ * _HEAD + + + + + * _CLASS_HEAD + + + + * _HEAD_INITIALIZER + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + * _INIT + + + + * _EMPTY + + + + * _FIRST + + + + @@ -88,21 +94,31 @@ * _PREV - + - + * _LAST - - + + * _FOREACH + + + + + * _FOREACH_FROM + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + * _INSERT_HEAD + + + + * _INSERT_BEFORE - + - + * _INSERT_AFTER + + + + * _INSERT_TAIL - - + + - * _CONCAT - - + + + * _CONCAT s s + + * _REMOVE_AFTER + - + - * _REMOVE_HEAD + - + - - * _REMOVE + + + + + * _REMOVE s + s + * _SWAP + + + + * */ #ifdef QUEUE_MACRO_DEBUG +#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH +#define QUEUE_MACRO_DEBUG_TRACE +#define QUEUE_MACRO_DEBUG_TRASH +#endif + +#ifdef QUEUE_MACRO_DEBUG_TRACE /* Store the last 2 places the queue element or head was altered */ struct qm_trace { unsigned long lastline; @@ -112,9 +128,7 @@ struct qm_trace { }; #define TRACEBUF struct qm_trace trace; -#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } , -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) -#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , #define QMD_TRACE_HEAD(head) do { \ (head)->trace.prevline = (head)->trace.lastline; \ @@ -130,14 +144,35 @@ struct qm_trace { (elem)->trace.lastfile = __FILE__; \ } while (0) -#else +#else /* !QUEUE_MACRO_DEBUG_TRACE */ #define QMD_TRACE_ELEM(elem) #define QMD_TRACE_HEAD(head) -#define QMD_SAVELINK(name, link) #define TRACEBUF #define TRACEBUF_INITIALIZER +#endif /* QUEUE_MACRO_DEBUG_TRACE */ + +#ifdef QUEUE_MACRO_DEBUG_TRASH +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1) +#else /* !QUEUE_MACRO_DEBUG_TRASH */ #define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ +#define QMD_IS_TRASHED(x) 0 +#endif /* QUEUE_MACRO_DEBUG_TRASH */ + +#if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) +#else /* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */ +#define QMD_SAVELINK(name, link) +#endif /* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif /* * Singly-linked List declarations. @@ -147,6 +182,11 @@ struct name { \ struct type *slh_first; /* first element */ \ } +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + #define SLIST_HEAD_INITIALIZER(head) \ { NULL } @@ -155,9 +195,37 @@ struct { \ struct type *sle_next; /* next element */ \ } +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + /* * Singly-linked List functions. */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \ + if (*(prevp) != (elm)) \ + panic("Bad prevptr *(%p) == %p != %p", \ + (prevp), *(prevp), (elm)); \ +} while (0) +#else +#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) +#endif + +#define SLIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \ + SLIST_INIT(head2); \ + } else if (SLIST_FIRST(head2) != NULL) { \ + while (SLIST_NEXT(curelm, field) != NULL) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \ + SLIST_INIT(head2); \ + } \ +} while (0) + #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) @@ -167,11 +235,21 @@ struct { \ (var); \ (var) = SLIST_NEXT((var), field)) +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + #define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ for ((varp) = &SLIST_FIRST((head)); \ ((var) = *(varp)) != NULL; \ @@ -199,7 +277,7 @@ struct { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ - struct type *curelm = SLIST_FIRST((head)); \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ while (SLIST_NEXT(curelm, field) != (elm)) \ curelm = SLIST_NEXT(curelm, field); \ SLIST_REMOVE_AFTER(curelm, field); \ @@ -216,8 +294,14 @@ struct { \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ } while (0) +#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \ + QMD_SLIST_CHECK_PREVPTR(prevp, elm); \ + *(prevp) = SLIST_NEXT(elm, field); \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + #define SLIST_SWAP(head1, head2, type) do { \ - struct type *swap_first = SLIST_FIRST(head1); \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ SLIST_FIRST(head1) = SLIST_FIRST(head2); \ SLIST_FIRST(head2) = swap_first; \ } while (0) @@ -231,6 +315,12 @@ struct name { \ struct type **stqh_last;/* addr of last next element */ \ } +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } @@ -239,6 +329,11 @@ struct { \ struct type *stqe_next; /* next element */ \ } +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + /* * Singly-linked Tail queue functions. */ @@ -259,12 +354,21 @@ struct { \ (var); \ (var) = STAILQ_NEXT((var), field)) +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + #define STAILQ_INIT(head) do { \ STAILQ_FIRST((head)) = NULL; \ (head)->stqh_last = &STAILQ_FIRST((head)); \ @@ -288,9 +392,10 @@ struct { \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? NULL : \ - __containerof((head)->stqh_last, struct type, field.stqe_next)) +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) @@ -300,7 +405,7 @@ struct { \ STAILQ_REMOVE_HEAD((head), field); \ } \ else { \ - struct type *curelm = STAILQ_FIRST((head)); \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ while (STAILQ_NEXT(curelm, field) != (elm)) \ curelm = STAILQ_NEXT(curelm, field); \ STAILQ_REMOVE_AFTER(head, curelm, field); \ @@ -326,8 +431,8 @@ struct { \ } while (0) #define STAILQ_SWAP(head1, head2, type) do { \ - struct type *swap_first = STAILQ_FIRST(head1); \ - struct type **swap_last = (head1)->stqh_last; \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_FIRST(head2) = swap_first; \ @@ -347,6 +452,11 @@ struct name { \ struct type *lh_first; /* first element */ \ } +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + #define LIST_HEAD_INITIALIZER(head) \ { NULL } @@ -356,11 +466,23 @@ struct { \ struct type **le_prev; /* address of previous next element */ \ } +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + /* * List functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME) + * + * If the list is non-empty, validates that the first element of the list + * points back at 'head.' + */ #define QMD_LIST_CHECK_HEAD(head, field) do { \ if (LIST_FIRST((head)) != NULL && \ LIST_FIRST((head))->field.le_prev != \ @@ -368,6 +490,12 @@ struct { \ panic("Bad list head %p first->prev != head", (head)); \ } while (0) +/* + * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME) + * + * If an element follows 'elm' in the list, validates that the next element + * points back at 'elm.' + */ #define QMD_LIST_CHECK_NEXT(elm, field) do { \ if (LIST_NEXT((elm), field) != NULL && \ LIST_NEXT((elm), field)->field.le_prev != \ @@ -375,6 +503,11 @@ struct { \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) +/* + * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME) + * + * Validates that the previous element (or head of the list) points to 'elm.' + */ #define QMD_LIST_CHECK_PREV(elm, field) do { \ if (*(elm)->field.le_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ @@ -385,6 +518,23 @@ struct { \ #define QMD_LIST_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) */ +#define LIST_CONCAT(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \ + if (curelm == NULL) { \ + if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \ + LIST_FIRST(head2)->field.le_prev = \ + &LIST_FIRST((head1)); \ + LIST_INIT(head2); \ + } \ + } else if (LIST_FIRST(head2) != NULL) { \ + while (LIST_NEXT(curelm, field) != NULL) \ + curelm = LIST_NEXT(curelm, field); \ + LIST_NEXT(curelm, field) = LIST_FIRST(head2); \ + LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \ + LIST_INIT(head2); \ + } \ +} while (0) + #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) @@ -394,11 +544,21 @@ struct { \ (var); \ (var) = LIST_NEXT((var), field)) +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + #define LIST_INIT(head) do { \ LIST_FIRST((head)) = NULL; \ } while (0) @@ -430,9 +590,10 @@ struct { \ #define LIST_NEXT(elm, field) ((elm)->field.le_next) -#define LIST_PREV(elm, head, type, field) \ - ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ - __containerof((elm)->field.le_prev, struct type, field.le_next)) +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) #define LIST_REMOVE(elm, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.le_next); \ @@ -448,7 +609,7 @@ struct { \ } while (0) #define LIST_SWAP(head1, head2, type, field) do { \ - struct type *swap_tmp = LIST_FIRST((head1)); \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ LIST_FIRST((head1)) = LIST_FIRST((head2)); \ LIST_FIRST((head2)) = swap_tmp; \ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ @@ -467,6 +628,13 @@ struct name { \ TRACEBUF \ } +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } @@ -477,10 +645,23 @@ struct { \ TRACEBUF \ } +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + /* * Tail queue functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) +/* + * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * If the tailq is non-empty, validates that the first element of the tailq + * points back at 'head.' + */ #define QMD_TAILQ_CHECK_HEAD(head, field) do { \ if (!TAILQ_EMPTY(head) && \ TAILQ_FIRST((head))->field.tqe_prev != \ @@ -488,11 +669,22 @@ struct { \ panic("Bad tailq head %p first->prev != head", (head)); \ } while (0) +/* + * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME) + * + * Validates that the tail of the tailq is a pointer to pointer to NULL. + */ #define QMD_TAILQ_CHECK_TAIL(head, field) do { \ if (*(head)->tqh_last != NULL) \ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ } while (0) +/* + * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME) + * + * If an element follows 'elm' in the tailq, validates that the next element + * points back at 'elm.' + */ #define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ if (TAILQ_NEXT((elm), field) != NULL && \ TAILQ_NEXT((elm), field)->field.tqe_prev != \ @@ -500,6 +692,11 @@ struct { \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) +/* + * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME) + * + * Validates that the previous element (or head of the tailq) points to 'elm.' + */ #define QMD_TAILQ_CHECK_PREV(elm, field) do { \ if (*(elm)->field.tqe_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ @@ -531,21 +728,41 @@ struct { \ (var); \ (var) = TAILQ_NEXT((var), field)) +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = TAILQ_LAST((head), headname); \ (var); \ (var) = TAILQ_PREV((var), headname, field)) +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ for ((var) = TAILQ_LAST((head), headname); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ (var) = (tvar)) +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + #define TAILQ_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; \ (head)->tqh_last = &TAILQ_FIRST((head)); \ @@ -564,7 +781,7 @@ struct { \ TAILQ_NEXT((listelm), field) = (elm); \ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ } while (0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ @@ -574,7 +791,7 @@ struct { \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ } while (0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ @@ -627,8 +844,8 @@ struct { \ } while (0) #define TAILQ_SWAP(head1, head2, type, field) do { \ - struct type *swap_first = (head1)->tqh_first; \ - struct type **swap_last = (head1)->tqh_last; \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ (head1)->tqh_first = (head2)->tqh_first; \ (head1)->tqh_last = (head2)->tqh_last; \ (head2)->tqh_first = swap_first; \ diff --git a/libc/xtensa-lx106-elf/include/sys/reent.h b/libc/xtensa-lx106-elf/include/sys/reent.h index ce5b3ed..c045ca5 100644 --- a/libc/xtensa-lx106-elf/include/sys/reent.h +++ b/libc/xtensa-lx106-elf/include/sys/reent.h @@ -37,6 +37,8 @@ typedef __uint32_t __ULong; struct _reent; +struct __locale_t; + /* * If _REENT_SMALL is defined, we make struct _reent as small as possible, * by having nearly everything possible allocated at first use. @@ -384,8 +386,8 @@ struct _reent int __sdidinit; /* 1 means stdio has been init'd */ - int _current_category; /* unused */ - _CONST char *_current_locale; /* unused */ + int _unspecified_locale_info; /* unused, reserved for locale stuff */ + struct __locale_t *_locale;/* per-thread locale */ struct _mprec *_mp; @@ -429,7 +431,7 @@ extern const struct __sFILE_fake __sf_fake_stderr; _NULL, \ 0, \ 0, \ - "C", \ + _NULL, \ _NULL, \ _NULL, \ 0, \ @@ -446,16 +448,14 @@ extern const struct __sFILE_fake __sf_fake_stderr; _NULL \ } -#define _REENT_INIT_PTR(var) \ - { memset((var), 0, sizeof(*(var))); \ - (var)->_stdin = (__FILE *)&__sf_fake_stdin; \ +#define _REENT_INIT_PTR_ZEROED(var) \ + { (var)->_stdin = (__FILE *)&__sf_fake_stdin; \ (var)->_stdout = (__FILE *)&__sf_fake_stdout; \ (var)->_stderr = (__FILE *)&__sf_fake_stderr; \ - (var)->_current_locale = "C"; \ } -/* Only built the assert() calls if we are built with debugging. */ -#if DEBUG +/* Only add assert() calls if we are specified to debug. */ +#ifdef _REENT_CHECK_DEBUG #include #define __reent_assert(x) assert(x) #else @@ -578,8 +578,9 @@ struct _reent int _inc; /* used by tmpnam */ char _emergency[_REENT_EMERGENCY_SIZE]; - int _current_category; /* used by setlocale */ - _CONST char *_current_locale; + /* TODO */ + int _unspecified_locale_info; /* unused, reserved for locale stuff */ + struct __locale_t *_locale;/* per-thread locale */ int __sdidinit; /* 1 means stdio has been init'd */ @@ -643,18 +644,27 @@ struct _reent of the above members (on the off chance that future binary compatibility would be broken otherwise). */ struct _glue __sglue; /* root of glue chain */ +# ifndef _REENT_GLOBAL_STDIO_STREAMS __FILE __sf[3]; /* first three file descriptors */ +# endif }; +#ifdef _REENT_GLOBAL_STDIO_STREAMS +extern __FILE __sf[3]; +#define _REENT_STDIO_STREAM(var, index) &__sf[index] +#else +#define _REENT_STDIO_STREAM(var, index) &(var)->__sf[index] +#endif + #define _REENT_INIT(var) \ { 0, \ - &(var).__sf[0], \ - &(var).__sf[1], \ - &(var).__sf[2], \ + _REENT_STDIO_STREAM(&(var), 0), \ + _REENT_STDIO_STREAM(&(var), 1), \ + _REENT_STDIO_STREAM(&(var), 2), \ 0, \ "", \ 0, \ - "C", \ + _NULL, \ 0, \ _NULL, \ _NULL, \ @@ -694,12 +704,10 @@ struct _reent {_NULL, 0, _NULL} \ } -#define _REENT_INIT_PTR(var) \ - { memset((var), 0, sizeof(*(var))); \ - (var)->_stdin = &(var)->__sf[0]; \ - (var)->_stdout = &(var)->__sf[1]; \ - (var)->_stderr = &(var)->__sf[2]; \ - (var)->_current_locale = "C"; \ +#define _REENT_INIT_PTR_ZEROED(var) \ + { (var)->_stdin = _REENT_STDIO_STREAM(var, 0); \ + (var)->_stdout = _REENT_STDIO_STREAM(var, 1); \ + (var)->_stderr = _REENT_STDIO_STREAM(var, 2); \ (var)->_new._reent._rand_next = 1; \ (var)->_new._reent._r48._seed[0] = _RAND48_SEED_0; \ (var)->_new._reent._r48._seed[1] = _RAND48_SEED_1; \ @@ -745,6 +753,11 @@ struct _reent #endif /* !_REENT_SMALL */ +#define _REENT_INIT_PTR(var) \ + { memset((var), 0, sizeof(*(var))); \ + _REENT_INIT_PTR_ZEROED(var); \ + } + /* This value is used in stdlib/misc.c. reent/reent.c has to know it as well to make sure the freelist is correctly free'd. Therefore we define it here, rather than in stdlib/misc.c, as before. */ diff --git a/libc/xtensa-lx106-elf/include/sys/sched.h b/libc/xtensa-lx106-elf/include/sys/sched.h index 58f99d6..4adb6e2 100644 --- a/libc/xtensa-lx106-elf/include/sys/sched.h +++ b/libc/xtensa-lx106-elf/include/sys/sched.h @@ -21,6 +21,8 @@ #ifndef _SYS_SCHED_H_ #define _SYS_SCHED_H_ +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/libc/xtensa-lx106-elf/include/sys/select.h b/libc/xtensa-lx106-elf/include/sys/select.h new file mode 100644 index 0000000..f5dc586 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/select.h @@ -0,0 +1,87 @@ +/* select.h + Copyright 1998, 1999, 2000, 2001, 2005, 2009 Red Hat, Inc. + + Written by Geoffrey Noer + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H + +/* We don't define fd_set and friends if we are compiling POSIX + source, or if we have included (or may include as indicated + by __USE_W32_SOCKETS) the W32api winsock[2].h header which + defines Windows versions of them. Note that a program which + includes the W32api winsock[2].h header must know what it is doing; + it must not call the Cygwin select function. +*/ +# if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) + +#include +#include +#include +#include + +#if !defined(_SIGSET_T_DECLARED) +#define _SIGSET_T_DECLARED +typedef __sigset_t sigset_t; +#endif + +# define _SYS_TYPES_FD_SET +/* + * Select uses bit masks of file descriptors in longs. + * These macros manipulate such bit fields (the filesystem macros use chars). + * FD_SETSIZE may be defined by the user, but the default here + * should be >= NOFILE (param.h). + */ +# ifndef FD_SETSIZE +# define FD_SETSIZE 64 +# endif + +typedef unsigned long fd_mask; +# define NFDBITS (sizeof (fd_mask) * 8) /* bits per mask */ +# ifndef _howmany +# define _howmany(x,y) (((x)+((y)-1))/(y)) +# endif + +/* We use a macro for fd_set so that including Sockets.h afterwards + can work. */ +typedef struct _types_fd_set { + fd_mask fds_bits[_howmany(FD_SETSIZE, NFDBITS)]; +} _types_fd_set; + +#define fd_set _types_fd_set + +# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS))) +# define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS))) +# define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS))) +# define FD_ZERO(p) (__extension__ (void)({ \ + size_t __i; \ + char *__tmp = (char *)p; \ + for (__i = 0; __i < sizeof (*(p)); ++__i) \ + *__tmp++ = 0; \ +})) + +#if !defined (__INSIDE_CYGWIN_NET__) + +__BEGIN_DECLS + +int select __P ((int __n, fd_set *__readfds, fd_set *__writefds, + fd_set *__exceptfds, struct timeval *__timeout)); +#if __POSIX_VISIBLE >= 200112 +int pselect __P ((int __n, fd_set *__readfds, fd_set *__writefds, + fd_set *__exceptfds, const struct timespec *__timeout, + const sigset_t *__set)); +#endif + +__END_DECLS + +#endif /* !__INSIDE_CYGWIN_NET__ */ + +#endif /* !(_WINSOCK_H || _WINSOCKAPI_ || __USE_W32_SOCKETS) */ + +#endif /* sys/select.h */ diff --git a/libc/xtensa-lx106-elf/include/sys/signal.h b/libc/xtensa-lx106-elf/include/sys/signal.h index a29f525..ab35718 100644 --- a/libc/xtensa-lx106-elf/include/sys/signal.h +++ b/libc/xtensa-lx106-elf/include/sys/signal.h @@ -7,19 +7,22 @@ extern "C" { #endif #include "_ansi.h" +#include #include #include +#include +#include -/* #ifndef __STRICT_ANSI__*/ - -/* Cygwin defines it's own sigset_t in include/cygwin/signal.h */ -#ifndef __CYGWIN__ -typedef unsigned long sigset_t; +#if !defined(_SIGSET_T_DECLARED) +#define _SIGSET_T_DECLARED +typedef __sigset_t sigset_t; #endif -#if defined(__rtems__) +#if defined(__CYGWIN__) +#include +#else -#if defined(_POSIX_REALTIME_SIGNALS) +#if defined(_POSIX_REALTIME_SIGNALS) || __POSIX_VISIBLE >= 199309 /* sigev_notify values NOTE: P1003.1c/D10, p. 34 adds SIGEV_THREAD. */ @@ -67,14 +70,16 @@ typedef struct { int si_code; /* Cause of the signal */ union sigval si_value; /* Signal value */ } siginfo_t; -#endif +#endif /* defined(_POSIX_REALTIME_SIGNALS) || __POSIX_VISIBLE >= 199309 */ + +#if defined(__rtems__) /* 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 */ #define SA_NOCLDSTOP 0x1 /* Do not generate SIGCHLD when children stop */ #define SA_SIGINFO 0x2 /* Invoke the signal catching function with */ /* three arguments instead of one. */ -#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809 #define SA_ONSTACK 0x4 /* Signal delivery will be on a separate stack. */ #endif @@ -107,7 +112,22 @@ struct sigaction { #define sa_sigaction _signal_handlers._sigaction #endif -#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +#else /* defined(__rtems__) */ + +#define SA_NOCLDSTOP 1 /* only value supported now for sa_flags */ + +typedef void (*_sig_func_ptr)(int); + +struct sigaction +{ + _sig_func_ptr sa_handler; + sigset_t sa_mask; + int sa_flags; +}; +#endif /* defined(__rtems__) */ +#endif /* defined(__CYGWIN__) */ + +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809 /* * Minimum and default signal stack constants. Allow for target overrides * from . @@ -125,6 +145,8 @@ struct sigaction { #define SS_ONSTACK 0x1 #define SS_DISABLE 0x2 +#endif + /* * Structure used in sigaltstack call. */ @@ -133,58 +155,33 @@ typedef struct sigaltstack { int ss_flags; /* Flags. */ size_t ss_size; /* Stack size. */ } stack_t; -#endif - -#elif defined(__CYGWIN__) -#include -#else -#define SA_NOCLDSTOP 1 /* only value supported now for sa_flags */ - -typedef void (*_sig_func_ptr)(int); - -struct sigaction -{ - _sig_func_ptr sa_handler; - sigset_t sa_mask; - int sa_flags; -}; -#endif /* defined(__rtems__) */ +#if __POSIX_VISIBLE #define SIG_SETMASK 0 /* set mask with sigprocmask() */ #define SIG_BLOCK 1 /* set of signals to block */ #define SIG_UNBLOCK 2 /* set of signals to, well, unblock */ -/* These depend upon the type of sigset_t, which right now - is always a long.. They're in the POSIX namespace, but - are not ANSI. */ -#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0) -#define sigdelset(what,sig) (*(what) &= ~(1<<(sig)), 0) -#define sigemptyset(what) (*(what) = 0, 0) -#define sigfillset(what) (*(what) = ~(0), 0) -#define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0) - int _EXFUN(sigprocmask, (int how, const sigset_t *set, sigset_t *oset)); +#endif -#if defined(_POSIX_THREADS) +#if __POSIX_VISIBLE >= 199506 int _EXFUN(pthread_sigmask, (int how, const sigset_t *set, sigset_t *oset)); #endif #if defined(__CYGWIN__) || defined(__rtems__) -#undef sigaddset -#undef sigdelset -#undef sigemptyset -#undef sigfillset -#undef sigismember - #ifdef _COMPILING_NEWLIB int _EXFUN(_kill, (pid_t, int)); #endif /* _COMPILING_NEWLIB */ #endif /* __CYGWIN__ || __rtems__ */ -#if defined(__CYGWIN__) || defined(__rtems__) || defined(__SPU__) + +#if __POSIX_VISIBLE int _EXFUN(kill, (pid_t, int)); -#endif /* __CYGWIN__ || __rtems__ || __SPU__ */ -#if defined(__CYGWIN__) || defined(__rtems__) +#endif + +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 int _EXFUN(killpg, (pid_t, int)); +#endif +#if __POSIX_VISIBLE int _EXFUN(sigaction, (int, const struct sigaction *, struct sigaction *)); int _EXFUN(sigaddset, (sigset_t *, const int)); int _EXFUN(sigdelset, (sigset_t *, const int)); @@ -193,24 +190,45 @@ int _EXFUN(sigfillset, (sigset_t *)); int _EXFUN(sigemptyset, (sigset_t *)); int _EXFUN(sigpending, (sigset_t *)); int _EXFUN(sigsuspend, (const sigset_t *)); -int _EXFUN(sigpause, (int)); +int _EXFUN(sigwait, (const sigset_t *set, int *sig)); -#ifdef __rtems__ -#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 +#if !defined(__CYGWIN__) && !defined(__rtems__) +/* These depend upon the type of sigset_t, which right now + is always a long.. They're in the POSIX namespace, but + are not ANSI. */ +#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0) +#define sigdelset(what,sig) (*(what) &= ~(1<<(sig)), 0) +#define sigemptyset(what) (*(what) = 0, 0) +#define sigfillset(what) (*(what) = ~(0), 0) +#define sigismember(what,sig) (((*(what)) & (1<<(sig))) != 0) +#endif /* !__CYGWIN__ && !__rtems__ */ +#endif /* __POSIX_VISIBLE */ + +/* There are two common sigpause variants, both of which take an int argument. + If you request _XOPEN_SOURCE or _GNU_SOURCE, you get the System V version, + which removes the given signal from the process's signal mask; otherwise + you get the BSD version, which sets the process's signal mask to the given + value. */ +#if __XSI_VISIBLE && !defined(__INSIDE_CYGWIN__) +# ifdef __GNUC__ +int _EXFUN(sigpause, (int)) __asm__ (__ASMNAME ("__xpg_sigpause")); +# else +int _EXFUN(__xpg_sigpause, (int)); +# define sigpause __xpg_sigpause +# endif +#elif __BSD_VISIBLE +int _EXFUN(sigpause, (int)); +#endif + +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809 int _EXFUN(sigaltstack, (const stack_t *__restrict, stack_t *__restrict)); #endif -#endif -#if defined(_POSIX_THREADS) -#ifdef __CYGWIN__ -# ifndef _CYGWIN_TYPES_H -# error You need the winsup sources or a cygwin installation to compile the cygwin version of newlib. -# endif -#endif +#if __POSIX_VISIBLE >= 199506 int _EXFUN(pthread_kill, (pthread_t thread, int sig)); #endif -#if defined(_POSIX_REALTIME_SIGNALS) +#if __POSIX_VISIBLE >= 199309 /* 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76 NOTE: P1003.1c/D10, p. 39 adds sigwait(). */ @@ -219,16 +237,10 @@ int _EXFUN(sigwaitinfo, (const sigset_t *set, siginfo_t *info)); int _EXFUN(sigtimedwait, (const sigset_t *set, siginfo_t *info, const struct timespec *timeout) ); -int _EXFUN(sigwait, (const sigset_t *set, int *sig)); - /* 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78 */ int _EXFUN(sigqueue, (pid_t pid, int signo, const union sigval value)); -#endif /* defined(_POSIX_REALTIME_SIGNALS) */ - -#endif /* defined(__CYGWIN__) || defined(__rtems__) */ - -/* #endif __STRICT_ANSI__ */ +#endif /* __POSIX_VISIBLE >= 199309 */ #if defined(___AM29K__) /* These all need to be defined for ANSI C, but I don't think they are @@ -349,6 +361,12 @@ int _EXFUN(sigqueue, (pid_t pid, int signo, const union sigval value)); } #endif +#if defined(__CYGWIN__) +#if __XSI_VISIBLE >= 4 || __POSIX_VISIBLE >= 200809 +#include +#endif +#endif + #ifndef _SIGNAL_H_ /* Some applications take advantage of the fact that * and are equivalent in glibc. Allow for that here. */ diff --git a/libc/xtensa-lx106-elf/include/sys/stat.h b/libc/xtensa-lx106-elf/include/sys/stat.h index 11b9d80..94a90c0 100644 --- a/libc/xtensa-lx106-elf/include/sys/stat.h +++ b/libc/xtensa-lx106-elf/include/sys/stat.h @@ -9,6 +9,7 @@ extern "C" { #include #include #include +#include /* dj's stat defines _STAT_H_ */ #ifndef _STAT_H_ @@ -52,8 +53,8 @@ struct stat long st_spare2; time_t st_ctime; long st_spare3; - long st_blksize; - long st_blocks; + blksize_t st_blksize; + blkcnt_t st_blocks; long st_spare4[2]; #endif #endif @@ -81,12 +82,12 @@ struct stat #define S_ISUID 0004000 /* set user id on execution */ #define S_ISGID 0002000 /* set group id on execution */ #define S_ISVTX 0001000 /* save swapped text even after use */ -#ifndef _POSIX_SOURCE +#if __BSD_VISIBLE #define S_IREAD 0000400 /* read permission, owner */ #define S_IWRITE 0000200 /* write permission, owner */ #define S_IEXEC 0000100 /* execute/search permission, owner */ #define S_ENFMT 0002000 /* enforcement-mode locking */ -#endif /* !_POSIX_SOURCE */ +#endif /* !_BSD_VISIBLE */ #define S_IFMT _IFMT #define S_IFDIR _IFDIR @@ -123,7 +124,7 @@ struct stat #define S_IWOTH 0000002 /* write permission, other */ #define S_IXOTH 0000001/* execute/search permission, other */ -#ifndef _POSIX_SOURCE +#if __BSD_VISIBLE #define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO) /* 0777 */ #define ALLPERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) /* 07777 */ #define DEFFILEMODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) /* 0666 */ @@ -156,19 +157,15 @@ int _EXFUN(lstat,( const char *__restrict __path, struct stat *__restrict __buf int _EXFUN(mknod,( const char *__path, mode_t __mode, dev_t __dev )); #endif -#if (__POSIX_VISIBLE >= 200809 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) +#if __ATFILE_VISIBLE && !defined(__INSIDE_CYGWIN__) int _EXFUN(fchmodat, (int, const char *, mode_t, int)); -#endif -#if (__BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) int _EXFUN(fstatat, (int, const char *__restrict , struct stat *__restrict, int)); int _EXFUN(mkdirat, (int, const char *, mode_t)); int _EXFUN(mkfifoat, (int, const char *, mode_t)); -#endif -#if (__BSD_VISIBLE || __XSI_VISIBLE >= 700 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) int _EXFUN(mknodat, (int, const char *, mode_t, dev_t)); -#endif -#if (__BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || defined (__CYGWIN__)) && !defined(__INSIDE_CYGWIN__) int _EXFUN(utimensat, (int, const char *, const struct timespec *, int)); +#endif +#if __POSIX_VISIBLE >= 200809 && !defined(__INSIDE_CYGWIN__) int _EXFUN(futimens, (int, const struct timespec *)); #endif diff --git a/libc/xtensa-lx106-elf/include/sys/time.h b/libc/xtensa-lx106-elf/include/sys/time.h index be16497..5fdb667 100644 --- a/libc/xtensa-lx106-elf/include/sys/time.h +++ b/libc/xtensa-lx106-elf/include/sys/time.h @@ -2,90 +2,301 @@ Written by Geoffrey Noer Public domain; no rights reserved. */ +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.5 (Berkeley) 5/4/95 + * $FreeBSD$ + */ + #ifndef _SYS_TIME_H_ -#define _SYS_TIME_H_ +#define _SYS_TIME_H_ #include <_ansi.h> +#include +#include #include +#include -#ifdef __cplusplus -extern "C" { +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE +#include #endif -#ifndef _TIMEVAL_DEFINED -#define _TIMEVAL_DEFINED -struct timeval { - time_t tv_sec; - suseconds_t tv_usec; -}; - -/* BSD time macros used by RTEMS code */ -#if defined (__rtems__) || defined (__CYGWIN__) - -/* Convenience macros for operations on timevals. - NOTE: `timercmp' does not work for >= or <=. */ -#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) -#define timercmp(a, b, CMP) \ - (((a)->tv_sec == (b)->tv_sec) ? \ - ((a)->tv_usec CMP (b)->tv_usec) : \ - ((a)->tv_sec CMP (b)->tv_sec)) -#define timeradd(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ - if ((result)->tv_usec >= 1000000) \ - { \ - ++(result)->tv_sec; \ - (result)->tv_usec -= 1000000; \ - } \ - } while (0) -#define timersub(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ - } while (0) -#endif /* defined (__rtems__) || defined (__CYGWIN__) */ -#endif /* !_TIMEVAL_DEFINED */ - struct timezone { - int tz_minuteswest; - int tz_dsttime; + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; +#define DST_NONE 0 /* not on dst */ +#define DST_USA 1 /* USA style dst */ +#define DST_AUST 2 /* Australian style dst */ +#define DST_WET 3 /* Western European dst */ +#define DST_MET 4 /* Middle European dst */ +#define DST_EET 5 /* Eastern European dst */ +#define DST_CAN 6 /* Canada */ + +#if __BSD_VISIBLE +struct bintime { + time_t sec; + uint64_t frac; }; -#ifdef __CYGWIN__ -#include -#endif /* __CYGWIN__ */ +static __inline void +bintime_addx(struct bintime *_bt, uint64_t _x) +{ + uint64_t _u; -#define ITIMER_REAL 0 -#define ITIMER_VIRTUAL 1 -#define ITIMER_PROF 2 + _u = _bt->frac; + _bt->frac += _x; + if (_u > _bt->frac) + _bt->sec++; +} -struct itimerval { - struct timeval it_interval; - struct timeval it_value; +static __inline void +bintime_add(struct bintime *_bt, const struct bintime *_bt2) +{ + uint64_t _u; + + _u = _bt->frac; + _bt->frac += _bt2->frac; + if (_u > _bt->frac) + _bt->sec++; + _bt->sec += _bt2->sec; +} + +static __inline void +bintime_sub(struct bintime *_bt, const struct bintime *_bt2) +{ + uint64_t _u; + + _u = _bt->frac; + _bt->frac -= _bt2->frac; + if (_u < _bt->frac) + _bt->sec--; + _bt->sec -= _bt2->sec; +} + +static __inline void +bintime_mul(struct bintime *_bt, u_int _x) +{ + uint64_t _p1, _p2; + + _p1 = (_bt->frac & 0xffffffffull) * _x; + _p2 = (_bt->frac >> 32) * _x + (_p1 >> 32); + _bt->sec *= _x; + _bt->sec += (_p2 >> 32); + _bt->frac = (_p2 << 32) | (_p1 & 0xffffffffull); +} + +static __inline void +bintime_shift(struct bintime *_bt, int _exp) +{ + + if (_exp > 0) { + _bt->sec <<= _exp; + _bt->sec |= _bt->frac >> (64 - _exp); + _bt->frac <<= _exp; + } else if (_exp < 0) { + _bt->frac >>= -_exp; + _bt->frac |= (uint64_t)_bt->sec << (64 + _exp); + _bt->sec >>= -_exp; + } +} + +#define bintime_clear(a) ((a)->sec = (a)->frac = 0) +#define bintime_isset(a) ((a)->sec || (a)->frac) +#define bintime_cmp(a, b, cmp) \ + (((a)->sec == (b)->sec) ? \ + ((a)->frac cmp (b)->frac) : \ + ((a)->sec cmp (b)->sec)) + +#define SBT_1S ((sbintime_t)1 << 32) +#define SBT_1M (SBT_1S * 60) +#define SBT_1MS (SBT_1S / 1000) +#define SBT_1US (SBT_1S / 1000000) +#define SBT_1NS (SBT_1S / 1000000000) +#define SBT_MAX 0x7fffffffffffffffLL + +static __inline int +sbintime_getsec(sbintime_t _sbt) +{ + + return (_sbt >> 32); +} + +static __inline sbintime_t +bttosbt(const struct bintime _bt) +{ + + return (((sbintime_t)_bt.sec << 32) + (_bt.frac >> 32)); +} + +static __inline struct bintime +sbttobt(sbintime_t _sbt) +{ + struct bintime _bt; + + _bt.sec = _sbt >> 32; + _bt.frac = _sbt << 32; + return (_bt); +} + +/*- + * Background information: + * + * When converting between timestamps on parallel timescales of differing + * resolutions it is historical and scientific practice to round down rather + * than doing 4/5 rounding. + * + * The date changes at midnight, not at noon. + * + * Even at 15:59:59.999999999 it's not four'o'clock. + * + * time_second ticks after N.999999999 not after N.4999999999 + */ + +static __inline void +bintime2timespec(const struct bintime *_bt, struct timespec *_ts) +{ + + _ts->tv_sec = _bt->sec; + _ts->tv_nsec = ((uint64_t)1000000000 * + (uint32_t)(_bt->frac >> 32)) >> 32; +} + +static __inline void +timespec2bintime(const struct timespec *_ts, struct bintime *_bt) +{ + + _bt->sec = _ts->tv_sec; + /* 18446744073 = int(2^64 / 1000000000) */ + _bt->frac = _ts->tv_nsec * (uint64_t)18446744073LL; +} + +static __inline void +bintime2timeval(const struct bintime *_bt, struct timeval *_tv) +{ + + _tv->tv_sec = _bt->sec; + _tv->tv_usec = ((uint64_t)1000000 * (uint32_t)(_bt->frac >> 32)) >> 32; +} + +static __inline void +timeval2bintime(const struct timeval *_tv, struct bintime *_bt) +{ + + _bt->sec = _tv->tv_sec; + /* 18446744073709 = int(2^64 / 1000000) */ + _bt->frac = _tv->tv_usec * (uint64_t)18446744073709LL; +} + +static __inline struct timespec +sbttots(sbintime_t _sbt) +{ + struct timespec _ts; + + _ts.tv_sec = _sbt >> 32; + _ts.tv_nsec = ((uint64_t)1000000000 * (uint32_t)_sbt) >> 32; + return (_ts); +} + +static __inline sbintime_t +tstosbt(struct timespec _ts) +{ + + return (((sbintime_t)_ts.tv_sec << 32) + + (_ts.tv_nsec * (((uint64_t)1 << 63) / 500000000) >> 32)); +} + +static __inline struct timeval +sbttotv(sbintime_t _sbt) +{ + struct timeval _tv; + + _tv.tv_sec = _sbt >> 32; + _tv.tv_usec = ((uint64_t)1000000 * (uint32_t)_sbt) >> 32; + return (_tv); +} + +static __inline sbintime_t +tvtosbt(struct timeval _tv) +{ + + return (((sbintime_t)_tv.tv_sec << 32) + + (_tv.tv_usec * (((uint64_t)1 << 63) / 500000) >> 32)); +} +#endif /* __BSD_VISIBLE */ + +/* + * Names of the interval timers, and structure + * defining a timer setting. + */ +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +struct itimerval { + struct timeval it_interval; /* timer interval */ + struct timeval it_value; /* current value */ }; +#ifndef _KERNEL +#include + +__BEGIN_DECLS +int _EXFUN(utimes, (const char *__path, const struct timeval *__tvp)); + +#if __BSD_VISIBLE +int _EXFUN(adjtime, (const struct timeval *, struct timeval *)); +int _EXFUN(futimes, (int, const struct timeval *)); +int _EXFUN(lutimes, (const char *, const struct timeval *)); +int _EXFUN(settimeofday, (const struct timeval *, const struct timezone *)); +#endif + +#if __MISC_VISIBLE || __XSI_VISIBLE +int _EXFUN(getitimer, (int __which, struct itimerval *__value)); +int _EXFUN(setitimer, (int __which, const struct itimerval *__restrict __value, + struct itimerval *__restrict __ovalue)); +#endif + +int _EXFUN(gettimeofday, (struct timeval *__restrict __p, + void *__restrict __tz)); + +#if __GNU_VISIBLE +int _EXFUN(futimesat, (int, const char *, const struct timeval [2])); +#endif + #ifdef _COMPILING_NEWLIB int _EXFUN(_gettimeofday, (struct timeval *__p, void *__tz)); #endif -int _EXFUN(gettimeofday, (struct timeval *__restrict __p, - void *__restrict __tz)); -#if __BSD_VISIBLE -int _EXFUN(settimeofday, (const struct timeval *, const struct timezone *)); -int _EXFUN(adjtime, (const struct timeval *, struct timeval *)); -#endif -int _EXFUN(utimes, (const char *__path, const struct timeval *__tvp)); -int _EXFUN(getitimer, (int __which, struct itimerval *__value)); -int _EXFUN(setitimer, (int __which, const struct itimerval *__restrict __value, - struct itimerval *__restrict __ovalue)); +__END_DECLS -#ifdef __cplusplus -} -#endif -#endif /* _SYS_TIME_H_ */ +#endif /* !_KERNEL */ +#include + +#endif /* !_SYS_TIME_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/timeb.h b/libc/xtensa-lx106-elf/include/sys/timeb.h index 0a2c3de..793b481 100644 --- a/libc/xtensa-lx106-elf/include/sys/timeb.h +++ b/libc/xtensa-lx106-elf/include/sys/timeb.h @@ -15,11 +15,12 @@ extern "C" { #define _SYS_TIMEB_H #include <_ansi.h> -#include +#include -#ifndef __time_t_defined -typedef _TIME_T_ time_t; -#define __time_t_defined +#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED) +typedef _TIME_T_ time_t; +#define __time_t_defined +#define _TIME_T_DECLARED #endif struct timeb diff --git a/libc/xtensa-lx106-elf/include/sys/times.h b/libc/xtensa-lx106-elf/include/sys/times.h index 927812c..b1f1dc6 100644 --- a/libc/xtensa-lx106-elf/include/sys/times.h +++ b/libc/xtensa-lx106-elf/include/sys/times.h @@ -5,11 +5,12 @@ extern "C" { #define _SYS_TIMES_H #include <_ansi.h> -#include +#include -#ifndef __clock_t_defined -typedef _CLOCK_T_ clock_t; -#define __clock_t_defined +#if !defined(__clock_t_defined) && !defined(_CLOCK_T_DECLARED) +typedef _CLOCK_T_ clock_t; +#define __clock_t_defined +#define _CLOCK_T_DECLARED #endif /* Get Process Times, P1003.1b-1993, p. 92 */ diff --git a/libc/xtensa-lx106-elf/include/sys/timespec.h b/libc/xtensa-lx106-elf/include/sys/timespec.h new file mode 100644 index 0000000..2505cef --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/timespec.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.5 (Berkeley) 5/4/95 + * from: FreeBSD: src/sys/sys/time.h,v 1.43 2000/03/20 14:09:05 phk Exp + * $FreeBSD$ + */ + +#ifndef _SYS_TIMESPEC_H_ +#define _SYS_TIMESPEC_H_ + +#include +#include + +#if __BSD_VISIBLE +#define TIMEVAL_TO_TIMESPEC(tv, ts) \ + do { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ + } while (0) +#define TIMESPEC_TO_TIMEVAL(tv, ts) \ + do { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } while (0) + +#endif /* __BSD_VISIBLE */ + +/* + * Structure defined by POSIX.1b to be like a itimerval, but with + * timespecs. Used in the timer_*() system calls. + */ +struct itimerspec { + struct timespec it_interval; + struct timespec it_value; +}; + +#endif /* _SYS_TIMESPEC_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/tree.h b/libc/xtensa-lx106-elf/include/sys/tree.h new file mode 100644 index 0000000..f4167c4 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/sys/tree.h @@ -0,0 +1,801 @@ +/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */ +/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ +/* $FreeBSD$ */ + +/*- + * Copyright 2002 Niels Provos + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_TREE_H_ +#define _SYS_TREE_H_ + +#include + +/* + * This file defines data structures for different types of trees: + * splay trees and red-black trees. + * + * A splay tree is a self-organizing data structure. Every operation + * on the tree causes a splay to happen. The splay moves the requested + * node to the root of the tree and partly rebalances it. + * + * This has the benefit that request locality causes faster lookups as + * the requested nodes move to the top of the tree. On the other hand, + * every lookup causes memory writes. + * + * The Balance Theorem bounds the total access time for m operations + * and n inserts on an initially empty tree as O((m + n)lg n). The + * amortized cost for a sequence of m accesses to a splay tree is O(lg n); + * + * A red-black tree is a binary search tree with the node color as an + * extra attribute. It fulfills a set of conditions: + * - every search path from the root to a leaf consists of the + * same number of black nodes, + * - each red node (except for the root) has a black parent, + * - each leaf node is black. + * + * Every operation on a red-black tree is bounded as O(lg n). + * The maximum height of a red-black tree is 2lg (n+1). + */ + +#define SPLAY_HEAD(name, type) \ +struct name { \ + struct type *sph_root; /* root of the tree */ \ +} + +#define SPLAY_INITIALIZER(root) \ + { NULL } + +#define SPLAY_INIT(root) do { \ + (root)->sph_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ENTRY(type) \ +struct { \ + struct type *spe_left; /* left element */ \ + struct type *spe_right; /* right element */ \ +} + +#define SPLAY_LEFT(elm, field) (elm)->field.spe_left +#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right +#define SPLAY_ROOT(head) (head)->sph_root +#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL) + +/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */ +#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + (head)->sph_root = tmp; \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_LINKLEFT(head, tmp, field) do { \ + SPLAY_LEFT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_LINKRIGHT(head, tmp, field) do { \ + SPLAY_RIGHT(tmp, field) = (head)->sph_root; \ + tmp = (head)->sph_root; \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \ +} while (/*CONSTCOND*/ 0) + +#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \ + SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \ + SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \ + SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ + +#define SPLAY_PROTOTYPE(name, type, field, cmp) \ +void name##_SPLAY(struct name *, struct type *); \ +void name##_SPLAY_MINMAX(struct name *, int); \ +struct type *name##_SPLAY_INSERT(struct name *, struct type *); \ +struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \ + \ +/* Finds the node with the same key as elm */ \ +static __inline struct type * \ +name##_SPLAY_FIND(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) \ + return(NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) \ + return (head->sph_root); \ + return (NULL); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_NEXT(struct name *head, struct type *elm) \ +{ \ + name##_SPLAY(head, elm); \ + if (SPLAY_RIGHT(elm, field) != NULL) { \ + elm = SPLAY_RIGHT(elm, field); \ + while (SPLAY_LEFT(elm, field) != NULL) { \ + elm = SPLAY_LEFT(elm, field); \ + } \ + } else \ + elm = NULL; \ + return (elm); \ +} \ + \ +static __inline struct type * \ +name##_SPLAY_MIN_MAX(struct name *head, int val) \ +{ \ + name##_SPLAY_MINMAX(head, val); \ + return (SPLAY_ROOT(head)); \ +} + +/* Main splay operation. + * Moves node close to the key of elm to top + */ +#define SPLAY_GENERATE(name, type, field, cmp) \ +struct type * \ +name##_SPLAY_INSERT(struct name *head, struct type *elm) \ +{ \ + if (SPLAY_EMPTY(head)) { \ + SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \ + } else { \ + int __comp; \ + name##_SPLAY(head, elm); \ + __comp = (cmp)(elm, (head)->sph_root); \ + if(__comp < 0) { \ + SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\ + SPLAY_RIGHT(elm, field) = (head)->sph_root; \ + SPLAY_LEFT((head)->sph_root, field) = NULL; \ + } else if (__comp > 0) { \ + SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\ + SPLAY_LEFT(elm, field) = (head)->sph_root; \ + SPLAY_RIGHT((head)->sph_root, field) = NULL; \ + } else \ + return ((head)->sph_root); \ + } \ + (head)->sph_root = (elm); \ + return (NULL); \ +} \ + \ +struct type * \ +name##_SPLAY_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *__tmp; \ + if (SPLAY_EMPTY(head)) \ + return (NULL); \ + name##_SPLAY(head, elm); \ + if ((cmp)(elm, (head)->sph_root) == 0) { \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \ + (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\ + } else { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\ + name##_SPLAY(head, elm); \ + SPLAY_RIGHT((head)->sph_root, field) = __tmp; \ + } \ + return (elm); \ + } \ + return (NULL); \ +} \ + \ +void \ +name##_SPLAY(struct name *head, struct type *elm) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ + int __comp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if ((cmp)(elm, __tmp) > 0){ \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} \ + \ +/* Splay with either the minimum or the maximum element \ + * Used to find minimum or maximum element in tree. \ + */ \ +void name##_SPLAY_MINMAX(struct name *head, int __comp) \ +{ \ + struct type __node, *__left, *__right, *__tmp; \ +\ + SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\ + __left = __right = &__node; \ +\ + while (1) { \ + if (__comp < 0) { \ + __tmp = SPLAY_LEFT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp < 0){ \ + SPLAY_ROTATE_RIGHT(head, __tmp, field); \ + if (SPLAY_LEFT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKLEFT(head, __right, field); \ + } else if (__comp > 0) { \ + __tmp = SPLAY_RIGHT((head)->sph_root, field); \ + if (__tmp == NULL) \ + break; \ + if (__comp > 0) { \ + SPLAY_ROTATE_LEFT(head, __tmp, field); \ + if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\ + break; \ + } \ + SPLAY_LINKRIGHT(head, __left, field); \ + } \ + } \ + SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \ +} + +#define SPLAY_NEGINF -1 +#define SPLAY_INF 1 + +#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y) +#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y) +#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y) +#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y) +#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF)) +#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \ + : name##_SPLAY_MIN_MAX(x, SPLAY_INF)) + +#define SPLAY_FOREACH(x, name, head) \ + for ((x) = SPLAY_MIN(name, head); \ + (x) != NULL; \ + (x) = SPLAY_NEXT(name, head, x)) + +/* Macros that define a red-black tree */ +#define RB_HEAD(name, type) \ +struct name { \ + struct type *rbh_root; /* root of the tree */ \ +} + +#define RB_INITIALIZER(root) \ + { NULL } + +#define RB_INIT(root) do { \ + (root)->rbh_root = NULL; \ +} while (/*CONSTCOND*/ 0) + +#define RB_BLACK 0 +#define RB_RED 1 +#define RB_ENTRY(type) \ +struct { \ + struct type *rbe_left; /* left element */ \ + struct type *rbe_right; /* right element */ \ + struct type *rbe_parent; /* parent element */ \ + int rbe_color; /* node color */ \ +} + +#define RB_LEFT(elm, field) (elm)->field.rbe_left +#define RB_RIGHT(elm, field) (elm)->field.rbe_right +#define RB_PARENT(elm, field) (elm)->field.rbe_parent +#define RB_COLOR(elm, field) (elm)->field.rbe_color +#define RB_ROOT(head) (head)->rbh_root +#define RB_EMPTY(head) (RB_ROOT(head) == NULL) + +#define RB_SET(elm, parent, field) do { \ + RB_PARENT(elm, field) = parent; \ + RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ + RB_COLOR(elm, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#define RB_SET_BLACKRED(black, red, field) do { \ + RB_COLOR(black, field) = RB_BLACK; \ + RB_COLOR(red, field) = RB_RED; \ +} while (/*CONSTCOND*/ 0) + +#ifndef RB_AUGMENT +#define RB_AUGMENT(x) do {} while (0) +#endif + +#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ + (tmp) = RB_RIGHT(elm, field); \ + if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ + RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_LEFT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ + (tmp) = RB_LEFT(elm, field); \ + if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ + RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ + } \ + RB_AUGMENT(elm); \ + if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ + if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ + RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ + else \ + RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ + } else \ + (head)->rbh_root = (tmp); \ + RB_RIGHT(tmp, field) = (elm); \ + RB_PARENT(elm, field) = (tmp); \ + RB_AUGMENT(tmp); \ + if ((RB_PARENT(tmp, field))) \ + RB_AUGMENT(RB_PARENT(tmp, field)); \ +} while (/*CONSTCOND*/ 0) + +/* Generates prototypes and inline functions */ +#define RB_PROTOTYPE(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) +#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ + RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ + RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \ + RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \ + RB_PROTOTYPE_INSERT(name, type, attr); \ + RB_PROTOTYPE_REMOVE(name, type, attr); \ + RB_PROTOTYPE_FIND(name, type, attr); \ + RB_PROTOTYPE_NFIND(name, type, attr); \ + RB_PROTOTYPE_NEXT(name, type, attr); \ + RB_PROTOTYPE_PREV(name, type, attr); \ + RB_PROTOTYPE_MINMAX(name, type, attr); +#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \ + attr void name##_RB_INSERT_COLOR(struct name *, struct type *) +#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \ + attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *) +#define RB_PROTOTYPE_REMOVE(name, type, attr) \ + attr struct type *name##_RB_REMOVE(struct name *, struct type *) +#define RB_PROTOTYPE_INSERT(name, type, attr) \ + attr struct type *name##_RB_INSERT(struct name *, struct type *) +#define RB_PROTOTYPE_FIND(name, type, attr) \ + attr struct type *name##_RB_FIND(struct name *, struct type *) +#define RB_PROTOTYPE_NFIND(name, type, attr) \ + attr struct type *name##_RB_NFIND(struct name *, struct type *) +#define RB_PROTOTYPE_NEXT(name, type, attr) \ + attr struct type *name##_RB_NEXT(struct type *) +#define RB_PROTOTYPE_PREV(name, type, attr) \ + attr struct type *name##_RB_PREV(struct type *) +#define RB_PROTOTYPE_MINMAX(name, type, attr) \ + attr struct type *name##_RB_MINMAX(struct name *, int) + +/* Main rb operation. + * Moves node close to the key of elm to top + */ +#define RB_GENERATE(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp,) +#define RB_GENERATE_STATIC(name, type, field, cmp) \ + RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) +#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ + RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ + RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \ + RB_GENERATE_INSERT(name, type, field, cmp, attr) \ + RB_GENERATE_REMOVE(name, type, field, attr) \ + RB_GENERATE_FIND(name, type, field, cmp, attr) \ + RB_GENERATE_NFIND(name, type, field, cmp, attr) \ + RB_GENERATE_NEXT(name, type, field, attr) \ + RB_GENERATE_PREV(name, type, field, attr) \ + RB_GENERATE_MINMAX(name, type, field, attr) + +#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \ +attr void \ +name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ +{ \ + struct type *parent, *gparent, *tmp; \ + while ((parent = RB_PARENT(elm, field)) != NULL && \ + RB_COLOR(parent, field) == RB_RED) { \ + gparent = RB_PARENT(parent, field); \ + if (parent == RB_LEFT(gparent, field)) { \ + tmp = RB_RIGHT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_RIGHT(parent, field) == elm) { \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_RIGHT(head, gparent, tmp, field); \ + } else { \ + tmp = RB_LEFT(gparent, field); \ + if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ + RB_COLOR(tmp, field) = RB_BLACK; \ + RB_SET_BLACKRED(parent, gparent, field);\ + elm = gparent; \ + continue; \ + } \ + if (RB_LEFT(parent, field) == elm) { \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = parent; \ + parent = elm; \ + elm = tmp; \ + } \ + RB_SET_BLACKRED(parent, gparent, field); \ + RB_ROTATE_LEFT(head, gparent, tmp, field); \ + } \ + } \ + RB_COLOR(head->rbh_root, field) = RB_BLACK; \ +} + +#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \ +attr void \ +name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ +{ \ + struct type *tmp; \ + while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ + elm != RB_ROOT(head)) { \ + if (RB_LEFT(parent, field) == elm) { \ + tmp = RB_RIGHT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ + struct type *oleft; \ + if ((oleft = RB_LEFT(tmp, field)) \ + != NULL) \ + RB_COLOR(oleft, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_RIGHT(head, tmp, oleft, field);\ + tmp = RB_RIGHT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_RIGHT(tmp, field)) \ + RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_LEFT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } else { \ + tmp = RB_LEFT(parent, field); \ + if (RB_COLOR(tmp, field) == RB_RED) { \ + RB_SET_BLACKRED(tmp, parent, field); \ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + if ((RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ + (RB_RIGHT(tmp, field) == NULL || \ + RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ + RB_COLOR(tmp, field) = RB_RED; \ + elm = parent; \ + parent = RB_PARENT(elm, field); \ + } else { \ + if (RB_LEFT(tmp, field) == NULL || \ + RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ + struct type *oright; \ + if ((oright = RB_RIGHT(tmp, field)) \ + != NULL) \ + RB_COLOR(oright, field) = RB_BLACK;\ + RB_COLOR(tmp, field) = RB_RED; \ + RB_ROTATE_LEFT(head, tmp, oright, field);\ + tmp = RB_LEFT(parent, field); \ + } \ + RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ + RB_COLOR(parent, field) = RB_BLACK; \ + if (RB_LEFT(tmp, field)) \ + RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ + RB_ROTATE_RIGHT(head, parent, tmp, field);\ + elm = RB_ROOT(head); \ + break; \ + } \ + } \ + } \ + if (elm) \ + RB_COLOR(elm, field) = RB_BLACK; \ +} + +#define RB_GENERATE_REMOVE(name, type, field, attr) \ +attr struct type * \ +name##_RB_REMOVE(struct name *head, struct type *elm) \ +{ \ + struct type *child, *parent, *old = elm; \ + int color; \ + if (RB_LEFT(elm, field) == NULL) \ + child = RB_RIGHT(elm, field); \ + else if (RB_RIGHT(elm, field) == NULL) \ + child = RB_LEFT(elm, field); \ + else { \ + struct type *left; \ + elm = RB_RIGHT(elm, field); \ + while ((left = RB_LEFT(elm, field)) != NULL) \ + elm = left; \ + child = RB_RIGHT(elm, field); \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ + if (RB_PARENT(elm, field) == old) \ + parent = elm; \ + (elm)->field = (old)->field; \ + if (RB_PARENT(old, field)) { \ + if (RB_LEFT(RB_PARENT(old, field), field) == old)\ + RB_LEFT(RB_PARENT(old, field), field) = elm;\ + else \ + RB_RIGHT(RB_PARENT(old, field), field) = elm;\ + RB_AUGMENT(RB_PARENT(old, field)); \ + } else \ + RB_ROOT(head) = elm; \ + RB_PARENT(RB_LEFT(old, field), field) = elm; \ + if (RB_RIGHT(old, field)) \ + RB_PARENT(RB_RIGHT(old, field), field) = elm; \ + if (parent) { \ + left = parent; \ + do { \ + RB_AUGMENT(left); \ + } while ((left = RB_PARENT(left, field)) != NULL); \ + } \ + goto color; \ + } \ + parent = RB_PARENT(elm, field); \ + color = RB_COLOR(elm, field); \ + if (child) \ + RB_PARENT(child, field) = parent; \ + if (parent) { \ + if (RB_LEFT(parent, field) == elm) \ + RB_LEFT(parent, field) = child; \ + else \ + RB_RIGHT(parent, field) = child; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = child; \ +color: \ + if (color == RB_BLACK) \ + name##_RB_REMOVE_COLOR(head, parent, child); \ + return (old); \ +} \ + +#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \ +/* Inserts a node into the RB tree */ \ +attr struct type * \ +name##_RB_INSERT(struct name *head, struct type *elm) \ +{ \ + struct type *tmp; \ + struct type *parent = NULL; \ + int comp = 0; \ + tmp = RB_ROOT(head); \ + while (tmp) { \ + parent = tmp; \ + comp = (cmp)(elm, parent); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + RB_SET(elm, parent, field); \ + if (parent != NULL) { \ + if (comp < 0) \ + RB_LEFT(parent, field) = elm; \ + else \ + RB_RIGHT(parent, field) = elm; \ + RB_AUGMENT(parent); \ + } else \ + RB_ROOT(head) = elm; \ + name##_RB_INSERT_COLOR(head, elm); \ + return (NULL); \ +} + +#define RB_GENERATE_FIND(name, type, field, cmp, attr) \ +/* Finds the node with the same key as elm */ \ +attr struct type * \ +name##_RB_FIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) \ + tmp = RB_LEFT(tmp, field); \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (NULL); \ +} + +#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \ +/* Finds the first node greater than or equal to the search key */ \ +attr struct type * \ +name##_RB_NFIND(struct name *head, struct type *elm) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *res = NULL; \ + int comp; \ + while (tmp) { \ + comp = cmp(elm, tmp); \ + if (comp < 0) { \ + res = tmp; \ + tmp = RB_LEFT(tmp, field); \ + } \ + else if (comp > 0) \ + tmp = RB_RIGHT(tmp, field); \ + else \ + return (tmp); \ + } \ + return (res); \ +} + +#define RB_GENERATE_NEXT(name, type, field, attr) \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_NEXT(struct type *elm) \ +{ \ + if (RB_RIGHT(elm, field)) { \ + elm = RB_RIGHT(elm, field); \ + while (RB_LEFT(elm, field)) \ + elm = RB_LEFT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} + +#define RB_GENERATE_PREV(name, type, field, attr) \ +/* ARGSUSED */ \ +attr struct type * \ +name##_RB_PREV(struct type *elm) \ +{ \ + if (RB_LEFT(elm, field)) { \ + elm = RB_LEFT(elm, field); \ + while (RB_RIGHT(elm, field)) \ + elm = RB_RIGHT(elm, field); \ + } else { \ + if (RB_PARENT(elm, field) && \ + (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ + elm = RB_PARENT(elm, field); \ + else { \ + while (RB_PARENT(elm, field) && \ + (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ + elm = RB_PARENT(elm, field); \ + elm = RB_PARENT(elm, field); \ + } \ + } \ + return (elm); \ +} + +#define RB_GENERATE_MINMAX(name, type, field, attr) \ +attr struct type * \ +name##_RB_MINMAX(struct name *head, int val) \ +{ \ + struct type *tmp = RB_ROOT(head); \ + struct type *parent = NULL; \ + while (tmp) { \ + parent = tmp; \ + if (val < 0) \ + tmp = RB_LEFT(tmp, field); \ + else \ + tmp = RB_RIGHT(tmp, field); \ + } \ + return (parent); \ +} + +#define RB_NEGINF -1 +#define RB_INF 1 + +#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) +#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) +#define RB_FIND(name, x, y) name##_RB_FIND(x, y) +#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) +#define RB_NEXT(name, x, y) name##_RB_NEXT(y) +#define RB_PREV(name, x, y) name##_RB_PREV(y) +#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) +#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) + +#define RB_FOREACH(x, name, head) \ + for ((x) = RB_MIN(name, head); \ + (x) != NULL; \ + (x) = name##_RB_NEXT(x)) + +#define RB_FOREACH_FROM(x, name, y) \ + for ((x) = (y); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_SAFE(x, name, head, y) \ + for ((x) = RB_MIN(name, head); \ + ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE(x, name, head) \ + for ((x) = RB_MAX(name, head); \ + (x) != NULL; \ + (x) = name##_RB_PREV(x)) + +#define RB_FOREACH_REVERSE_FROM(x, name, y) \ + for ((x) = (y); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ + (x) = (y)) + +#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \ + for ((x) = RB_MAX(name, head); \ + ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \ + (x) = (y)) + +#endif /* _SYS_TREE_H_ */ diff --git a/libc/xtensa-lx106-elf/include/sys/types.h b/libc/xtensa-lx106-elf/include/sys/types.h index ed33e0a..65ff520 100644 --- a/libc/xtensa-lx106-elf/include/sys/types.h +++ b/libc/xtensa-lx106-elf/include/sys/types.h @@ -18,20 +18,12 @@ #ifndef _SYS_TYPES_H #include <_ansi.h> - -#ifndef __INTTYPES_DEFINED__ -#define __INTTYPES_DEFINED__ - +#include #include -#if defined(__rtems__) || defined(__XMK__) -/* - * The following section is RTEMS specific and is needed to more - * closely match the types defined in the BSD sys/types.h. - * This is needed to let the RTEMS/BSD TCP/IP stack compile. - */ - -/* deprecated */ +/* BSD types permitted by POSIX and always exposed as in Glibc. Only provided + for backward compatibility with BSD code. The uintN_t standard types should + be preferred in new code. */ #if ___int8_t_defined typedef __uint8_t u_int8_t; #endif @@ -41,52 +33,54 @@ typedef __uint16_t u_int16_t; #if ___int32_t_defined typedef __uint32_t u_int32_t; #endif - #if ___int64_t_defined typedef __uint64_t u_int64_t; +#endif +typedef int register_t; +#define __BIT_TYPES_DEFINED__ 1 + +#if defined(__rtems__) || defined(__XMK__) +/* + * The following section is RTEMS specific and is needed to more + * closely match the types defined in the BSD sys/types.h. + * This is needed to let the RTEMS/BSD TCP/IP stack compile. + */ /* deprecated */ +#if ___int64_t_defined typedef __uint64_t u_quad_t; typedef __int64_t quad_t; typedef quad_t * qaddr_t; #endif -#endif - -#endif /* ! __INTTYPES_DEFINED */ +#endif /* __rtems__ || __XMK__ */ #ifndef __need_inttypes #define _SYS_TYPES_H +/* must be before for __size_t considerations */ +#include #include +#include -#ifdef __i386__ -#if defined (GO32) || defined (__MSDOS__) -#define __MS_types__ -#endif -#endif - -# include -# include - -/* To ensure the stat struct's layout doesn't change when sizeof(int), etc. - changes, we assume sizeof short and long never change and have all types - used to define struct stat use them and not int where possible. - Where not possible, _ST_INTxx are used. It would be preferable to not have - such assumptions, but until the extra fluff is necessary, it's avoided. - No 64 bit targets use stat yet. What to do about them is postponed - until necessary. */ -#ifdef __GNUC__ -#define _ST_INT32 __attribute__ ((__mode__ (__SI__))) -#else -#define _ST_INT32 -#endif - -# ifndef _POSIX_SOURCE - +#if __BSD_VISIBLE +#include +#include # define physadr physadr_t # define quad quad_t +#ifndef _IN_ADDR_T_DECLARED +typedef __uint32_t in_addr_t; /* base type for internet address */ +#define _IN_ADDR_T_DECLARED +#endif + +#ifndef _IN_PORT_T_DECLARED +typedef __uint16_t in_port_t; +#define _IN_PORT_T_DECLARED +#endif +#endif /* __BSD_VISIBLE */ + +#if __MISC_VISIBLE #ifndef _BSDTYPES_DEFINED /* also defined in mingw/gmon.h and in w32api/winsock[2].h */ #ifndef __u_char_defined @@ -107,36 +101,35 @@ typedef unsigned long u_long; #endif #define _BSDTYPES_DEFINED #endif +#endif /*__BSD_VISIBLE || __CYGWIN__ */ +#if __MISC_VISIBLE typedef unsigned short ushort; /* System V compatibility */ typedef unsigned int uint; /* System V compatibility */ typedef unsigned long ulong; /* System V compatibility */ -# endif /*!_POSIX_SOURCE */ - -#ifndef __clock_t_defined -typedef _CLOCK_T_ clock_t; -#define __clock_t_defined #endif -#ifndef __time_t_defined -typedef _TIME_T_ time_t; -#define __time_t_defined +#ifndef _BLKCNT_T_DECLARED +typedef __blkcnt_t blkcnt_t; +#define _BLKCNT_T_DECLARED #endif -#ifndef __timespec_defined -#define __timespec_defined -/* Time Value Specification Structures, P1003.1b-1993, p. 261 */ - -struct timespec { - time_t tv_sec; /* Seconds */ - long tv_nsec; /* Nanoseconds */ -}; +#ifndef _BLKSIZE_T_DECLARED +typedef __blksize_t blksize_t; +#define _BLKSIZE_T_DECLARED #endif -struct itimerspec { - struct timespec it_interval; /* Timer period */ - struct timespec it_value; /* Timer expiration */ -}; +#if !defined(__clock_t_defined) && !defined(_CLOCK_T_DECLARED) +typedef _CLOCK_T_ clock_t; +#define __clock_t_defined +#define _CLOCK_T_DECLARED +#endif + +#if !defined(__time_t_defined) && !defined(_TIME_T_DECLARED) +typedef _TIME_T_ time_t; +#define __time_t_defined +#define _TIME_T_DECLARED +#endif #ifndef __daddr_t_defined typedef long daddr_t; @@ -147,31 +140,27 @@ typedef char * caddr_t; #define __caddr_t_defined #endif -#ifndef __CYGWIN__ -#if defined(__MS_types__) || defined(__rtems__) || \ - defined(__sparc__) || defined(__SPU__) -typedef unsigned long ino_t; -#else -typedef unsigned short ino_t; +#ifndef _FSBLKCNT_T_DECLARED /* for statvfs() */ +typedef __fsblkcnt_t fsblkcnt_t; +typedef __fsfilcnt_t fsfilcnt_t; +#define _FSBLKCNT_T_DECLARED #endif -#endif /*__CYGWIN__*/ -#ifdef __MS_types__ +#ifndef _ID_T_DECLARED +typedef __id_t id_t; /* can hold a uid_t or pid_t */ +#define _ID_T_DECLARED +#endif + +#ifndef _INO_T_DECLARED +typedef __ino_t ino_t; /* inode number */ +#define _INO_T_DECLARED +#endif + +#if defined(__i386__) && (defined(GO32) || defined(__MSDOS__)) +typedef char * addr_t; typedef unsigned long vm_offset_t; typedef unsigned long vm_size_t; - -#define __BIT_TYPES_DEFINED__ - -typedef signed char int8_t; -typedef unsigned char u_int8_t; -typedef short int16_t; -typedef unsigned short u_int16_t; -typedef int int32_t; -typedef unsigned int u_int32_t; -typedef long long int64_t; -typedef unsigned long long u_int64_t; -typedef int32_t register_t; -#endif /* __MS_types__ */ +#endif /* __i386__ && (GO32 || __MSDOS__) */ /* * All these should be machine specific - right now they are all broken. @@ -180,339 +169,75 @@ typedef int32_t register_t; * how the file was compiled (e.g. -mint16 vs -mint32, etc.). */ -#ifndef __CYGWIN__ /* which defines these types in it's own types.h. */ -typedef _off_t off_t; -typedef __dev_t dev_t; -typedef __uid_t uid_t; -typedef __gid_t gid_t; +#ifndef _OFF_T_DECLARED +typedef __off_t off_t; /* file offset */ +#define _OFF_T_DECLARED +#endif +#ifndef _DEV_T_DECLARED +typedef __dev_t dev_t; /* device number or struct cdev */ +#define _DEV_T_DECLARED +#endif +#ifndef _UID_T_DECLARED +typedef __uid_t uid_t; /* user id */ +#define _UID_T_DECLARED +#endif +#ifndef _GID_T_DECLARED +typedef __gid_t gid_t; /* group id */ +#define _GID_T_DECLARED #endif -#if defined(__XMK__) -typedef signed char pid_t; -#else -typedef int pid_t; +#ifndef _PID_T_DECLARED +typedef __pid_t pid_t; /* process id */ +#define _PID_T_DECLARED #endif -#if defined(__rtems__) -typedef _mode_t mode_t; +#ifndef _KEY_T_DECLARED +typedef __key_t key_t; /* IPC key */ +#define _KEY_T_DECLARED #endif -#ifndef __CYGWIN__ -typedef long key_t; -#endif +#ifndef _SSIZE_T_DECLARED typedef _ssize_t ssize_t; - -#if !defined(__CYGWIN__) && !defined(__rtems__) -#ifdef __MS_types__ -typedef char * addr_t; -typedef int mode_t; -#else -#if defined (__sparc__) && !defined (__sparc_v9__) -#ifdef __svr4__ -typedef unsigned long mode_t; -#else -typedef unsigned short mode_t; -#endif -#else -typedef unsigned int mode_t _ST_INT32; -#endif -#endif /* ! __MS_types__ */ -#endif /*__CYGWIN__*/ - -typedef unsigned short nlink_t; - -/* We don't define fd_set and friends if we are compiling POSIX - source, or if we have included (or may include as indicated - by __USE_W32_SOCKETS) the W32api winsock[2].h header which - defines Windows versions of them. Note that a program which - includes the W32api winsock[2].h header must know what it is doing; - it must not call the cygwin32 select function. -*/ -# if !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) -# define _SYS_TYPES_FD_SET -# define NBBY 8 /* number of bits in a byte */ -/* - * Select uses bit masks of file descriptors in longs. - * These macros manipulate such bit fields (the filesystem macros use chars). - * FD_SETSIZE may be defined by the user, but the default here - * should be >= NOFILE (param.h). - */ -# ifndef FD_SETSIZE -# define FD_SETSIZE 64 -# endif - -typedef long fd_mask; -# define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */ -# ifndef howmany -# define howmany(x,y) (((x)+((y)-1))/(y)) -# endif - -/* We use a macro for fd_set so that including Sockets.h afterwards - can work. */ -typedef struct _types_fd_set { - fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; -} _types_fd_set; - -#define fd_set _types_fd_set - -# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS))) -# define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS))) -# define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS))) -# define FD_ZERO(p) (__extension__ (void)({ \ - size_t __i; \ - char *__tmp = (char *)p; \ - for (__i = 0; __i < sizeof (*(p)); ++__i) \ - *__tmp++ = 0; \ -})) - -# endif /* !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) */ - -#undef __MS_types__ -#undef _ST_INT32 - - -#ifndef __clockid_t_defined -typedef _CLOCKID_T_ clockid_t; -#define __clockid_t_defined +#define _SSIZE_T_DECLARED #endif -#ifndef __timer_t_defined -typedef _TIMER_T_ timer_t; -#define __timer_t_defined +#ifndef _MODE_T_DECLARED +typedef __mode_t mode_t; /* permissions */ +#define _MODE_T_DECLARED #endif -typedef unsigned long useconds_t; -typedef long suseconds_t; +#ifndef _NLINK_T_DECLARED +typedef __nlink_t nlink_t; /* link count */ +#define _NLINK_T_DECLARED +#endif + +#if !defined(__clockid_t_defined) && !defined(_CLOCKID_T_DECLARED) +typedef __clockid_t clockid_t; +#define __clockid_t_defined +#define _CLOCKID_T_DECLARED +#endif + +#if !defined(__timer_t_defined) && !defined(_TIMER_T_DECLARED) +typedef __timer_t timer_t; +#define __timer_t_defined +#define _TIMER_T_DECLARED +#endif + +#ifndef _USECONDS_T_DECLARED +typedef __useconds_t useconds_t; /* microseconds (unsigned) */ +#define _USECONDS_T_DECLARED +#endif + +#ifndef _SUSECONDS_T_DECLARED +typedef __suseconds_t suseconds_t; +#define _SUSECONDS_T_DECLARED +#endif + +typedef __int64_t sbintime_t; #include - - -/* Cygwin will probably never have full posix compliance due to little things - * like an inability to set the stackaddress. Cygwin is also using void * - * pointers rather than structs to ensure maximum binary compatability with - * previous releases. - * This means that we don't use the types defined here, but rather in - * - */ -#if defined(_POSIX_THREADS) && !defined(__CYGWIN__) - -#include - -/* - * 2.5 Primitive System Data Types, P1003.1c/D10, p. 19. - */ - -#if defined(__XMK__) -typedef unsigned int pthread_t; /* identify a thread */ -#else -typedef __uint32_t pthread_t; /* identify a thread */ -#endif - -/* P1003.1c/D10, p. 118-119 */ -#define PTHREAD_SCOPE_PROCESS 0 -#define PTHREAD_SCOPE_SYSTEM 1 - -/* P1003.1c/D10, p. 111 */ -#define PTHREAD_INHERIT_SCHED 1 /* scheduling policy and associated */ - /* attributes are inherited from */ - /* the calling thread. */ -#define PTHREAD_EXPLICIT_SCHED 2 /* set from provided attribute object */ - -/* P1003.1c/D10, p. 141 */ -#define PTHREAD_CREATE_DETACHED 0 -#define PTHREAD_CREATE_JOINABLE 1 - -#if defined(__rtems__) - #include -#endif - -#if defined(__XMK__) -typedef struct pthread_attr_s { - int contentionscope; - struct sched_param schedparam; - int detachstate; - void *stackaddr; - size_t stacksize; -} pthread_attr_t; - -#define PTHREAD_STACK_MIN 200 - -#else /* !defined(__XMK__) */ -typedef struct { - int is_initialized; - void *stackaddr; - int stacksize; - int contentionscope; - int inheritsched; - int schedpolicy; - struct sched_param schedparam; -#if defined(__rtems__) - size_t guardsize; -#endif - - /* P1003.4b/D8, p. 54 adds cputime_clock_allowed attribute. */ -#if defined(_POSIX_THREAD_CPUTIME) - int cputime_clock_allowed; /* see time.h */ -#endif - int detachstate; -#if defined(__rtems__) - size_t affinitysetsize; - cpu_set_t *affinityset; - cpu_set_t affinitysetpreallocated; -#endif -} pthread_attr_t; - -#endif /* !defined(__XMK__) */ - -#if defined(_POSIX_THREAD_PROCESS_SHARED) -/* NOTE: P1003.1c/D10, p. 81 defines following values for process_shared. */ - -#define PTHREAD_PROCESS_PRIVATE 0 /* visible within only the creating process */ -#define PTHREAD_PROCESS_SHARED 1 /* visible too all processes with access to */ - /* the memory where the resource is */ - /* located */ -#endif - -#if defined(_POSIX_THREAD_PRIO_PROTECT) -/* Mutexes */ - -/* Values for blocking protocol. */ - -#define PTHREAD_PRIO_NONE 0 -#define PTHREAD_PRIO_INHERIT 1 -#define PTHREAD_PRIO_PROTECT 2 -#endif - -#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) - -/* Values for mutex type */ - -/* The following defines are part of the X/Open System Interface (XSI). */ - -/* - * This type of mutex does not detect deadlock. A thread attempting to - * relock this mutex without first unlocking it shall deadlock. Attempting - * to unlock a mutex locked by a different thread results in undefined - * behavior. Attempting to unlock an unlocked mutex results in undefined - * behavior. - */ -#define PTHREAD_MUTEX_NORMAL 0 - -/* - * A thread attempting to relock this mutex without first unlocking - * it shall succeed in locking the mutex. The relocking deadlock which - * can occur with mutexes of type PTHREAD_MUTEX_NORMAL cannot occur with - * this type of mutex. Multiple locks of this mutex shall require the - * same number of unlocks to release the mutex before another thread can - * acquire the mutex. A thread attempting to unlock a mutex which another - * thread has locked shall return with an error. A thread attempting to - * unlock an unlocked mutex shall return with an error. - */ -#define PTHREAD_MUTEX_RECURSIVE 1 - -/* - * This type of mutex provides error checking. A thread attempting - * to relock this mutex without first unlocking it shall return with an - * error. A thread attempting to unlock a mutex which another thread has - * locked shall return with an error. A thread attempting to unlock an - * unlocked mutex shall return with an error. - */ -#define PTHREAD_MUTEX_ERRORCHECK 2 - -/* - * Attempting to recursively lock a mutex of this type results - * in undefined behavior. Attempting to unlock a mutex of this type - * which was not locked by the calling thread results in undefined - * behavior. Attempting to unlock a mutex of this type which is not locked - * results in undefined behavior. An implementation may map this mutex to - * one of the other mutex types. - */ -#define PTHREAD_MUTEX_DEFAULT 3 - -#endif /* !defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) */ - -#if defined(__XMK__) -typedef unsigned int pthread_mutex_t; /* identify a mutex */ - -typedef struct { - int type; -} pthread_mutexattr_t; - -#else /* !defined(__XMK__) */ -typedef __uint32_t pthread_mutex_t; /* identify a mutex */ - -typedef struct { - int is_initialized; -#if defined(_POSIX_THREAD_PROCESS_SHARED) - int process_shared; /* allow mutex to be shared amongst processes */ -#endif -#if defined(_POSIX_THREAD_PRIO_PROTECT) - int prio_ceiling; - int protocol; -#endif -#if defined(_UNIX98_THREAD_MUTEX_ATTRIBUTES) - int type; -#endif - int recursive; -} pthread_mutexattr_t; -#endif /* !defined(__XMK__) */ - -/* Condition Variables */ - -typedef __uint32_t pthread_cond_t; /* identify a condition variable */ - -typedef struct { - int is_initialized; -#if defined(_POSIX_THREAD_PROCESS_SHARED) - int process_shared; /* allow this to be shared amongst processes */ -#endif -} pthread_condattr_t; /* a condition attribute object */ - -/* Keys */ - -typedef __uint32_t pthread_key_t; /* thread-specific data keys */ - -typedef struct { - int is_initialized; /* is this structure initialized? */ - int init_executed; /* has the initialization routine been run? */ -} pthread_once_t; /* dynamic package initialization */ -#else -#if defined (__CYGWIN__) -#include -#endif -#endif /* defined(_POSIX_THREADS) */ - -/* POSIX Barrier Types */ - -#if defined(_POSIX_BARRIERS) -typedef __uint32_t pthread_barrier_t; /* POSIX Barrier Object */ -typedef struct { - int is_initialized; /* is this structure initialized? */ -#if defined(_POSIX_THREAD_PROCESS_SHARED) - int process_shared; /* allow this to be shared amongst processes */ -#endif -} pthread_barrierattr_t; -#endif /* defined(_POSIX_BARRIERS) */ - -/* POSIX Spin Lock Types */ - -#if !defined (__CYGWIN__) -#if defined(_POSIX_SPIN_LOCKS) -typedef __uint32_t pthread_spinlock_t; /* POSIX Spin Lock Object */ -#endif /* defined(_POSIX_SPIN_LOCKS) */ - -/* POSIX Reader/Writer Lock Types */ - -#if defined(_POSIX_READER_WRITER_LOCKS) -typedef __uint32_t pthread_rwlock_t; /* POSIX RWLock Object */ -typedef struct { - int is_initialized; /* is this structure initialized? */ -#if defined(_POSIX_THREAD_PROCESS_SHARED) - int process_shared; /* allow this to be shared amongst processes */ -#endif -} pthread_rwlockattr_t; -#endif /* defined(_POSIX_READER_WRITER_LOCKS) */ -#endif /* __CYGWIN__ */ +#include +#include #endif /* !__need_inttypes */ diff --git a/libc/xtensa-lx106-elf/include/sys/unistd.h b/libc/xtensa-lx106-elf/include/sys/unistd.h index a741383..75f8a51 100644 --- a/libc/xtensa-lx106-elf/include/sys/unistd.h +++ b/libc/xtensa-lx106-elf/include/sys/unistd.h @@ -24,72 +24,89 @@ int _EXFUN(chmod, (const char *__path, mode_t __mode )); #if !defined(__INSIDE_CYGWIN__) int _EXFUN(chown, (const char *__path, uid_t __owner, gid_t __group )); #endif -#if defined(__CYGWIN__) || defined(__rtems__) +#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112) int _EXFUN(chroot, (const char *__path )); #endif int _EXFUN(close, (int __fildes )); -#if defined(__CYGWIN__) +#if __POSIX_VISIBLE >= 199209 size_t _EXFUN(confstr, (int __name, char *__buf, size_t __len)); #endif +#if __XSI_VISIBLE +char * _EXFUN(crypt, (const char *__key, const char *__salt)); +#endif +#if __XSI_VISIBLE && __XSI_VISIBLE < 700 char * _EXFUN(ctermid, (char *__s )); +#endif +#if __XSI_VISIBLE && __XSI_VISIBLE < 600 char * _EXFUN(cuserid, (char *__s )); -#if defined(__CYGWIN__) +#endif +#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) int _EXFUN(daemon, (int nochdir, int noclose)); #endif int _EXFUN(dup, (int __fildes )); int _EXFUN(dup2, (int __fildes, int __fildes2 )); -#if defined(__CYGWIN__) +#if __GNU_VISIBLE int _EXFUN(dup3, (int __fildes, int __fildes2, int flags)); int _EXFUN(eaccess, (const char *__path, int __mode)); +#endif +#if __XSI_VISIBLE +void _EXFUN(encrypt, (char *__block, int __edflag)); +#endif +#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) void _EXFUN(endusershell, (void)); +#endif +#if __GNU_VISIBLE int _EXFUN(euidaccess, (const char *__path, int __mode)); #endif int _EXFUN(execl, (const char *__path, const char *, ... )); int _EXFUN(execle, (const char *__path, const char *, ... )); int _EXFUN(execlp, (const char *__file, const char *, ... )); -#if defined(__CYGWIN__) +#if __MISC_VISIBLE int _EXFUN(execlpe, (const char *__file, const char *, ... )); #endif int _EXFUN(execv, (const char *__path, char * const __argv[] )); int _EXFUN(execve, (const char *__path, char * const __argv[], char * const __envp[] )); int _EXFUN(execvp, (const char *__file, char * const __argv[] )); -#if defined(__CYGWIN__) +#if __GNU_VISIBLE int _EXFUN(execvpe, (const char *__file, char * const __argv[], char * const __envp[] )); #endif -#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +#if __ATFILE_VISIBLE int _EXFUN(faccessat, (int __dirfd, const char *__path, int __mode, int __flags)); #endif -#if defined(__CYGWIN__) || defined(__rtems__) || defined(__SPU__) +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 int _EXFUN(fchdir, (int __fildes)); #endif int _EXFUN(fchmod, (int __fildes, mode_t __mode )); #if !defined(__INSIDE_CYGWIN__) int _EXFUN(fchown, (int __fildes, uid_t __owner, gid_t __group )); #endif -#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +#if __ATFILE_VISIBLE int _EXFUN(fchownat, (int __dirfd, const char *__path, uid_t __owner, gid_t __group, int __flags)); #endif -#if defined(__CYGWIN__) +#if __POSIX_VISIBLE >= 200809 int _EXFUN(fexecve, (int __fd, char * const __argv[], char * const __envp[] )); #endif pid_t _EXFUN(fork, (void )); long _EXFUN(fpathconf, (int __fd, int __name )); int _EXFUN(fsync, (int __fd)); int _EXFUN(fdatasync, (int __fd)); -#if defined(__CYGWIN__) +#if __GNU_VISIBLE char * _EXFUN(get_current_dir_name, (void)); #endif char * _EXFUN(getcwd, (char *__buf, size_t __size )); -#if defined(__CYGWIN__) +#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) int _EXFUN(getdomainname ,(char *__name, size_t __len)); #endif +#if __BSD_VISIBLE +int _EXFUN(getentropy, (void *, size_t)); +#endif #if !defined(__INSIDE_CYGWIN__) gid_t _EXFUN(getegid, (void )); uid_t _EXFUN(geteuid, (void )); gid_t _EXFUN(getgid, (void )); #endif int _EXFUN(getgroups, (int __gidsetsize, gid_t __grouplist[] )); -#if defined(__CYGWIN__) +#if __BSD_VISIBLE || __XSI_VISIBLE >= 4 long _EXFUN(gethostid, (void)); #endif char * _EXFUN(getlogin, (void )); @@ -98,37 +115,44 @@ int _EXFUN(getlogin_r, (char *name, size_t namesize) ); #endif char * _EXFUN(getpass, (const char *__prompt)); int _EXFUN(getpagesize, (void)); -#if defined(__CYGWIN__) +#if __BSD_VISIBLE int _EXFUN(getpeereid, (int, uid_t *, gid_t *)); #endif pid_t _EXFUN(getpgid, (pid_t)); pid_t _EXFUN(getpgrp, (void )); pid_t _EXFUN(getpid, (void )); pid_t _EXFUN(getppid, (void )); -#if defined(__CYGWIN__) || defined(__rtems__) +#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 4 pid_t _EXFUN(getsid, (pid_t)); #endif #if !defined(__INSIDE_CYGWIN__) uid_t _EXFUN(getuid, (void )); #endif -#ifdef __CYGWIN__ +#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) char * _EXFUN(getusershell, (void)); +#endif +#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200809) char * _EXFUN(getwd, (char *__buf )); +#endif +#if __BSD_VISIBLE int _EXFUN(iruserok, (unsigned long raddr, int superuser, const char *ruser, const char *luser)); #endif int _EXFUN(isatty, (int __fildes )); +#if __BSD_VISIBLE +int _EXFUN(issetugid, (void)); +#endif #if !defined(__INSIDE_CYGWIN__) int _EXFUN(lchown, (const char *__path, uid_t __owner, gid_t __group )); #endif int _EXFUN(link, (const char *__path1, const char *__path2 )); -#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +#if __ATFILE_VISIBLE int _EXFUN(linkat, (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags )); #endif int _EXFUN(nice, (int __nice_value )); #if !defined(__INSIDE_CYGWIN__) off_t _EXFUN(lseek, (int __fildes, off_t __offset, int __whence )); #endif -#if defined(__SPU__) || defined(__CYGWIN__) +#if __MISC_VISIBLE || __XSI_VISIBLE >= 4 #define F_ULOCK 0 #define F_LOCK 1 #define F_TLOCK 2 @@ -137,41 +161,41 @@ int _EXFUN(lockf, (int __fd, int __cmd, off_t __len)); #endif long _EXFUN(pathconf, (const char *__path, int __name )); int _EXFUN(pause, (void )); -#ifdef __CYGWIN__ +#if __POSIX_VISIBLE >= 199506 int _EXFUN(pthread_atfork, (void (*)(void), void (*)(void), void (*)(void))); #endif int _EXFUN(pipe, (int __fildes[2] )); -#ifdef __CYGWIN__ +#if __GNU_VISIBLE int _EXFUN(pipe2, (int __fildes[2], int flags)); #endif ssize_t _EXFUN(pread, (int __fd, void *__buf, size_t __nbytes, off_t __offset)); ssize_t _EXFUN(pwrite, (int __fd, const void *__buf, size_t __nbytes, off_t __offset)); _READ_WRITE_RETURN_TYPE _EXFUN(read, (int __fd, void *__buf, size_t __nbyte )); -#if defined(__CYGWIN__) +#if __BSD_VISIBLE int _EXFUN(rresvport, (int *__alport)); int _EXFUN(revoke, (char *__path)); #endif int _EXFUN(rmdir, (const char *__path )); -#if defined(__CYGWIN__) +#if __BSD_VISIBLE int _EXFUN(ruserok, (const char *rhost, int superuser, const char *ruser, const char *luser)); #endif void * _EXFUN(sbrk, (ptrdiff_t __incr)); #if !defined(__INSIDE_CYGWIN__) -#if defined(__CYGWIN__) || defined(__rtems__) +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 int _EXFUN(setegid, (gid_t __gid )); int _EXFUN(seteuid, (uid_t __uid )); #endif int _EXFUN(setgid, (gid_t __gid )); #endif -#if defined(__CYGWIN__) +#if __BSD_VISIBLE int _EXFUN(setgroups, (int ngroups, const gid_t *grouplist )); #endif -#if __BSD_VISIBLE || (defined(_XOPEN_SOURCE) && __XSI_VISIBLE < 500) +#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) int _EXFUN(sethostname, (const char *, size_t)); #endif int _EXFUN(setpgid, (pid_t __pid, pid_t __pgid )); int _EXFUN(setpgrp, (void )); -#if defined(__CYGWIN__) && !defined(__INSIDE_CYGWIN__) +#if (__BSD_VISIBLE || __XSI_VISIBLE >= 4) && !defined(__INSIDE_CYGWIN__) int _EXFUN(setregid, (gid_t __rgid, gid_t __egid)); int _EXFUN(setreuid, (uid_t __ruid, uid_t __euid)); #endif @@ -179,21 +203,25 @@ pid_t _EXFUN(setsid, (void )); #if !defined(__INSIDE_CYGWIN__) int _EXFUN(setuid, (uid_t __uid )); #endif -#if defined(__CYGWIN__) +#if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) void _EXFUN(setusershell, (void)); #endif unsigned _EXFUN(sleep, (unsigned int __seconds )); +#if __XSI_VISIBLE void _EXFUN(swab, (const void *__restrict, void *__restrict, ssize_t)); +#endif long _EXFUN(sysconf, (int __name )); pid_t _EXFUN(tcgetpgrp, (int __fildes )); int _EXFUN(tcsetpgrp, (int __fildes, pid_t __pgrp_id )); char * _EXFUN(ttyname, (int __fildes )); -#if defined(__CYGWIN__) || defined(__rtems__) -int _EXFUN(ttyname_r, (int, char *, size_t)); -#endif +int _EXFUN(ttyname_r, (int, char *, size_t)); int _EXFUN(unlink, (const char *__path )); +#if __XSI_VISIBLE >= 500 && __POSIX_VISIBLE < 200809 || __BSD_VISIBLE int _EXFUN(usleep, (useconds_t __useconds)); +#endif +#if __BSD_VISIBLE int _EXFUN(vhangup, (void )); +#endif _READ_WRITE_RETURN_TYPE _EXFUN(write, (int __fd, const void *__buf, size_t __nbyte )); #ifdef __CYGWIN__ @@ -207,9 +235,9 @@ int getopt(int, char * const [], const char *); extern int optreset; /* getopt(3) external variable */ #endif -#ifndef _POSIX_SOURCE +#if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200809) pid_t _EXFUN(vfork, (void )); -#endif /* _POSIX_SOURCE */ +#endif #ifdef _COMPILING_NEWLIB /* Provide prototypes for most of the _ names that are @@ -230,36 +258,45 @@ _READ_WRITE_RETURN_TYPE _EXFUN(_write, (int __fd, const void *__buf, size_t __nb int _EXFUN(_execve, (const char *__path, char * const __argv[], char * const __envp[] )); #endif -#if defined(__CYGWIN__) || defined(__rtems__) || defined(__aarch64__) || defined (__arm__) || defined(__sh__) || defined(__SPU__) #if !defined(__INSIDE_CYGWIN__) +#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 int _EXFUN(ftruncate, (int __fd, off_t __length)); +#endif +#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 int _EXFUN(truncate, (const char *, off_t __length)); #endif #endif -#if defined(__CYGWIN__) || defined(__rtems__) +#if __BSD_VISIBLE || __POSIX_VISIBLE < 200112 int _EXFUN(getdtablesize, (void)); -int _EXFUN(setdtablesize, (int)); +#endif +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 useconds_t _EXFUN(ualarm, (useconds_t __useconds, useconds_t __interval)); +#endif + +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 #if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) /* winsock[2].h defines as __stdcall, and with int as 2nd arg */ int _EXFUN(gethostname, (char *__name, size_t __len)); #endif -char * _EXFUN(mktemp, (char *)); #endif -#if defined(__CYGWIN__) || defined(__SPU__) || defined(__rtems__) +#if __MISC_VISIBLE +int _EXFUN(setdtablesize, (int)); +#endif + +#if __BSD_VISIBLE || __XSI_VISIBLE >= 500 void _EXFUN(sync, (void)); #endif +#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 4 ssize_t _EXFUN(readlink, (const char *__restrict __path, char *__restrict __buf, size_t __buflen)); -#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) +int _EXFUN(symlink, (const char *__name1, const char *__name2)); +#endif +#if __ATFILE_VISIBLE ssize_t _EXFUN(readlinkat, (int __dirfd1, const char *__restrict __path, char *__restrict __buf, size_t __buflen)); -#endif -int _EXFUN(symlink, (const char *__name1, const char *__name2)); -#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE || defined(__CYGWIN__) int _EXFUN(symlinkat, (const char *, int, const char *)); int _EXFUN(unlinkat, (int, const char *, int)); #endif @@ -422,6 +459,22 @@ int _EXFUN(unlinkat, (int, const char *, int)); #define _SC_THREAD_ROBUST_PRIO_INHERIT 122 #define _SC_THREAD_ROBUST_PRIO_PROTECT 123 #define _SC_XOPEN_UUCP 124 +#define _SC_LEVEL1_ICACHE_SIZE 125 +#define _SC_LEVEL1_ICACHE_ASSOC 126 +#define _SC_LEVEL1_ICACHE_LINESIZE 127 +#define _SC_LEVEL1_DCACHE_SIZE 128 +#define _SC_LEVEL1_DCACHE_ASSOC 129 +#define _SC_LEVEL1_DCACHE_LINESIZE 130 +#define _SC_LEVEL2_CACHE_SIZE 131 +#define _SC_LEVEL2_CACHE_ASSOC 132 +#define _SC_LEVEL2_CACHE_LINESIZE 133 +#define _SC_LEVEL3_CACHE_SIZE 134 +#define _SC_LEVEL3_CACHE_ASSOC 135 +#define _SC_LEVEL3_CACHE_LINESIZE 136 +#define _SC_LEVEL4_CACHE_SIZE 137 +#define _SC_LEVEL4_CACHE_ASSOC 138 +#define _SC_LEVEL4_CACHE_LINESIZE 139 +#define _SC_POSIX_26_VERSION 140 /* * pathconf values per IEEE Std 1003.1, 2008 Edition @@ -453,6 +506,7 @@ int _EXFUN(unlinkat, (int, const char *, int)); #define _PC_POSIX_PERMISSIONS 90 /* Ask for full POSIX permission support including uid/gid settings. */ #define _PC_POSIX_SECURITY 91 +#define _PC_CASE_INSENSITIVE 92 #endif /* diff --git a/libc/xtensa-lx106-elf/include/sys/wait.h b/libc/xtensa-lx106-elf/include/sys/wait.h index 73fe372..f17e53f 100644 --- a/libc/xtensa-lx106-elf/include/sys/wait.h +++ b/libc/xtensa-lx106-elf/include/sys/wait.h @@ -11,7 +11,7 @@ extern "C" { #define WUNTRACED 2 /* A status looks like: - <2 bytes info> <2 bytes code> + <1 byte info> <1 byte code> == 0, child has exited, info is the exit value == 1..7e, child has exited, info is the signal number. diff --git a/libc/xtensa-lx106-elf/include/tar.h b/libc/xtensa-lx106-elf/include/tar.h index 07b06dd..36437fc 100644 --- a/libc/xtensa-lx106-elf/include/tar.h +++ b/libc/xtensa-lx106-elf/include/tar.h @@ -5,6 +5,8 @@ #ifndef _TAR_H #define _TAR_H +#include + /* General definitions */ #define TMAGIC "ustar" /* ustar plus null byte. */ #define TMAGLEN 6 /* Length of the above. */ @@ -25,7 +27,9 @@ /* Mode field bit definitions (octal) */ #define TSUID 04000 /* Set UID on execution. */ #define TSGID 02000 /* Set GID on execution. */ +#if __XSI_VISIBLE || __POSIX_VISIBLE < 200112 #define TSVTX 01000 /* On directories, restricted deletion flag. */ +#endif #define TUREAD 00400 /* Read by owner. */ #define TUWRITE 00200 /* Write by owner. */ #define TUEXEC 00100 /* Execute/search by owner. */ diff --git a/libc/xtensa-lx106-elf/include/tgmath.h b/libc/xtensa-lx106-elf/include/tgmath.h index f9c8311..97dc50e 100644 --- a/libc/xtensa-lx106-elf/include/tgmath.h +++ b/libc/xtensa-lx106-elf/include/tgmath.h @@ -79,7 +79,7 @@ __tg_type3(__e1, __e2, __e3, long double _Complex) || \ __tg_type3(__e1, __e2, __e3, __typeof__(_Complex_I))) -#ifdef _LDBL_EQ_DBL +#if defined (_LDBL_EQ_DBL) || defined (__CYGWIN__) #define __tg_impl_simple(x, y, z, fn, fnf, fnl, ...) \ __builtin_choose_expr(__tg_type_corr(x, y, z, long double), \ fnl(__VA_ARGS__), __builtin_choose_expr( \ @@ -161,9 +161,10 @@ #define lround(__x) __tg_simple(__x, lround) #define nearbyint(__x) __tg_simple(__x, nearbyint) #define nextafter(__x, __y) __tg_simple2(__x, __y, nextafter) -/* not yet implemented even for _LDBL_EQ_DBL platforms +/* not yet implemented even for _LDBL_EQ_DBL platforms */ +#ifdef __CYGWIN__ #define nexttoward(__x, __y) __tg_simplev(__x, nexttoward, __x, __y) -*/ +#endif #define remainder(__x, __y) __tg_simple2(__x, __y, remainder) #define remquo(__x, __y, __z) __tg_impl_simple(__x, __x, __y, remquo, remquof, \ remquol, __x, __y, __z) diff --git a/libc/xtensa-lx106-elf/include/threads.h b/libc/xtensa-lx106-elf/include/threads.h new file mode 100644 index 0000000..9fb08b0 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/threads.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2011 Ed Schouten + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _THREADS_H_ +#define _THREADS_H_ + +#include +#include + +typedef void (*tss_dtor_t)(void *); +typedef int (*thrd_start_t)(void *); + +enum { + mtx_plain = 0x1, + mtx_recursive = 0x2, + mtx_timed = 0x4 +}; + +enum { + thrd_busy = 1, + thrd_error = 2, + thrd_nomem = 3, + thrd_success = 4, + thrd_timedout = 5 +}; + +#if !defined(__cplusplus) || __cplusplus < 201103L +#define thread_local _Thread_local +#endif + +__BEGIN_DECLS +void call_once(once_flag *, void (*)(void)); +int cnd_broadcast(cnd_t *); +void cnd_destroy(cnd_t *); +int cnd_init(cnd_t *); +int cnd_signal(cnd_t *); +int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict __mtx, + const struct timespec *__restrict) + __requires_exclusive(*__mtx); +int cnd_wait(cnd_t *, mtx_t *__mtx) + __requires_exclusive(*__mtx); +void mtx_destroy(mtx_t *__mtx) + __requires_unlocked(*__mtx); +int mtx_init(mtx_t *__mtx, int) + __requires_unlocked(*__mtx); +int mtx_lock(mtx_t *__mtx) + __locks_exclusive(*__mtx); +int mtx_timedlock(mtx_t *__restrict __mtx, + const struct timespec *__restrict) + __trylocks_exclusive(thrd_success, *__mtx); +int mtx_trylock(mtx_t *__mtx) + __trylocks_exclusive(thrd_success, *__mtx); +int mtx_unlock(mtx_t *__mtx) + __unlocks(*__mtx); +int thrd_create(thrd_t *, thrd_start_t, void *); +thrd_t thrd_current(void); +int thrd_detach(thrd_t); +int thrd_equal(thrd_t, thrd_t); +_Noreturn void + thrd_exit(int); +int thrd_join(thrd_t, int *); +int thrd_sleep(const struct timespec *, struct timespec *); +void thrd_yield(void); +int tss_create(tss_t *, tss_dtor_t); +void tss_delete(tss_t); +void * tss_get(tss_t); +int tss_set(tss_t, void *); +__END_DECLS + +#endif /* !_THREADS_H_ */ diff --git a/libc/xtensa-lx106-elf/include/time.h b/libc/xtensa-lx106-elf/include/time.h index d7b6612..8806b98 100644 --- a/libc/xtensa-lx106-elf/include/time.h +++ b/libc/xtensa-lx106-elf/include/time.h @@ -8,6 +8,7 @@ #define _TIME_H_ #include "_ansi.h" +#include #include #define __need_size_t @@ -25,6 +26,11 @@ #define CLK_TCK CLOCKS_PER_SEC #include +#include + +#if __POSIX_VISIBLE >= 200809 +#include +#endif _BEGIN_STD_C @@ -61,6 +67,12 @@ size_t _EXFUN(strftime, (char *__restrict _s, size_t _maxsize, const char *__restrict _fmt, const struct tm *__restrict _t)); +#if __POSIX_VISIBLE >= 200809 +extern size_t strftime_l (char *__restrict _s, size_t _maxsize, + const char *__restrict _fmt, + const struct tm *__restrict _t, locale_t _l); +#endif + char *_EXFUN(asctime_r, (const struct tm *__restrict, char *__restrict)); char *_EXFUN(ctime_r, (const time_t *, char *)); @@ -75,11 +87,19 @@ _END_STD_C extern "C" { #endif -#ifndef __STRICT_ANSI__ +#if __XSI_VISIBLE char *_EXFUN(strptime, (const char *__restrict, const char *__restrict, struct tm *__restrict)); +#endif +#if __GNU_VISIBLE +char *strptime_l (const char *__restrict, const char *__restrict, + struct tm *__restrict, locale_t); +#endif + +#if __POSIX_VISIBLE _VOID _EXFUN(tzset, (_VOID)); +#endif _VOID _EXFUN(_tzset_r, (struct _reent *)); typedef struct __tzrule_struct @@ -105,6 +125,7 @@ __tzinfo_type *_EXFUN (__gettzinfo, (_VOID)); /* getdate functions */ #ifdef HAVE_GETDATE +#if __XSI_VISIBLE >= 4 #ifndef _REENT_ONLY #define getdate_err (*__getdate_err()) int *_EXFUN(__getdate_err,(_VOID)); @@ -120,21 +141,27 @@ struct tm * _EXFUN(getdate, (const char *)); 7 there is no line in the template that matches the input, 8 invalid input specification */ #endif /* !_REENT_ONLY */ +#endif /* __XSI_VISIBLE >= 4 */ +#if __GNU_VISIBLE /* getdate_r returns the error code as above */ int _EXFUN(getdate_r, (const char *, struct tm *)); +#endif /* __GNU_VISIBLE */ #endif /* HAVE_GETDATE */ /* defines for the opengroup specifications Derived from Issue 1 of the SVID. */ +#if __SVID_VISIBLE || __XSI_VISIBLE extern __IMPORT long _timezone; extern __IMPORT int _daylight; +#endif +#if __POSIX_VISIBLE extern __IMPORT char *_tzname[2]; /* POSIX defines the external tzname being defined in time.h */ #ifndef tzname #define tzname _tzname #endif -#endif /* !__STRICT_ANSI__ */ +#endif /* __POSIX_VISIBLE */ #ifdef __cplusplus } diff --git a/libc/xtensa-lx106-elf/include/wchar.h b/libc/xtensa-lx106-elf/include/wchar.h index 810a6c0..6b4eff9 100644 --- a/libc/xtensa-lx106-elf/include/wchar.h +++ b/libc/xtensa-lx106-elf/include/wchar.h @@ -11,15 +11,32 @@ #define __need_NULL #include -#define __need___va_list -#include - /* For _mbstate_t definition. */ #include #include /* For __STDC_ISO_10646__ */ #include +/* typedef only __gnuc_va_list, used throughout the header */ +#define __need___va_list +#include + +/* typedef va_list only when required */ +#if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE +#ifdef __GNUC__ +#ifndef _VA_LIST_DEFINED +typedef __gnuc_va_list va_list; +#define _VA_LIST_DEFINED +#endif +#else /* !__GNUC__ */ +#include +#endif +#endif /* __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE */ + +#if __XSI_VISIBLE /* && __XSI_VISIBLE < 800 */ && !__GNU_VISIBLE +#include +#endif + #ifndef WEOF # define WEOF ((wint_t)-1) #endif @@ -46,10 +63,19 @@ #endif #endif +#if __POSIX_VISIBLE >= 200809 +#include +#endif + _BEGIN_STD_C +#if __POSIX_VISIBLE >= 200809 || _XSI_VISIBLE /* As in stdio.h, defines __FILE. */ +#if !defined(__FILE_defined) typedef __FILE FILE; +# define __FILE_defined +#endif +#endif /* As required by POSIX.1-2008, declare tm as incomplete type. The actual definition is in time.h. */ @@ -68,8 +94,10 @@ size_t _EXFUN(mbrtowc, (wchar_t *__restrict, const char *__restrict, size_t, size_t _EXFUN(_mbrtowc_r, (struct _reent *, wchar_t * , const char * , size_t, mbstate_t *)); int _EXFUN(mbsinit, (const mbstate_t *)); +#if __POSIX_VISIBLE >= 200809 size_t _EXFUN(mbsnrtowcs, (wchar_t *__restrict, const char **__restrict, size_t, size_t, mbstate_t *__restrict)); +#endif size_t _EXFUN(_mbsnrtowcs_r, (struct _reent *, wchar_t * , const char ** , size_t, size_t, mbstate_t *)); size_t _EXFUN(mbsrtowcs, (wchar_t *__restrict, const char **__restrict, size_t, @@ -77,39 +105,53 @@ size_t _EXFUN(mbsrtowcs, (wchar_t *__restrict, const char **__restrict, size_t, size_t _EXFUN(_mbsrtowcs_r, (struct _reent *, wchar_t * , const char ** , size_t, mbstate_t *)); size_t _EXFUN(wcrtomb, (char *__restrict, wchar_t, mbstate_t *__restrict)); size_t _EXFUN(_wcrtomb_r, (struct _reent *, char * , wchar_t, mbstate_t *)); +#if __POSIX_VISIBLE >= 200809 size_t _EXFUN(wcsnrtombs, (char *__restrict, const wchar_t **__restrict, size_t, size_t, mbstate_t *__restrict)); +#endif size_t _EXFUN(_wcsnrtombs_r, (struct _reent *, char * , const wchar_t ** , size_t, size_t, mbstate_t *)); size_t _EXFUN(wcsrtombs, (char *__restrict, const wchar_t **__restrict, size_t, mbstate_t *__restrict)); size_t _EXFUN(_wcsrtombs_r, (struct _reent *, char * , const wchar_t ** , size_t, mbstate_t *)); +#if __POSIX_VISIBLE >= 200809 int _EXFUN(wcscasecmp, (const wchar_t *, const wchar_t *)); +#endif wchar_t *_EXFUN(wcscat, (wchar_t *__restrict, const wchar_t *__restrict)); wchar_t *_EXFUN(wcschr, (const wchar_t *, wchar_t)); int _EXFUN(wcscmp, (const wchar_t *, const wchar_t *)); int _EXFUN(wcscoll, (const wchar_t *, const wchar_t *)); wchar_t *_EXFUN(wcscpy, (wchar_t *__restrict, const wchar_t *__restrict)); +#if __POSIX_VISIBLE >= 200809 wchar_t *_EXFUN(wcpcpy, (wchar_t *__restrict, const wchar_t *__restrict)); wchar_t *_EXFUN(wcsdup, (const wchar_t *)); +#endif wchar_t *_EXFUN(_wcsdup_r, (struct _reent *, const wchar_t * )); size_t _EXFUN(wcscspn, (const wchar_t *, const wchar_t *)); size_t _EXFUN(wcsftime, (wchar_t *__restrict, size_t, const wchar_t *__restrict, const struct tm *__restrict)); +#if __GNU_VISIBLE +size_t wcsftime_l (wchar_t *__restrict, size_t, const wchar_t *__restrict, + const struct tm *__restrict, locale_t); +#endif size_t _EXFUN(wcslcat, (wchar_t *, const wchar_t *, size_t)); size_t _EXFUN(wcslcpy, (wchar_t *, const wchar_t *, size_t)); size_t _EXFUN(wcslen, (const wchar_t *)); +#if __POSIX_VISIBLE >= 200809 int _EXFUN(wcsncasecmp, (const wchar_t *, const wchar_t *, size_t)); +#endif wchar_t *_EXFUN(wcsncat, (wchar_t *__restrict, const wchar_t *__restrict, size_t)); int _EXFUN(wcsncmp, (const wchar_t *, const wchar_t *, size_t)); wchar_t *_EXFUN(wcsncpy, (wchar_t *__restrict, const wchar_t *__restrict, size_t)); +#if __POSIX_VISIBLE >= 200809 wchar_t *_EXFUN(wcpncpy, (wchar_t *__restrict, const wchar_t *__restrict, size_t)); size_t _EXFUN(wcsnlen, (const wchar_t *, size_t)); +#endif wchar_t *_EXFUN(wcspbrk, (const wchar_t *, const wchar_t *)); wchar_t *_EXFUN(wcsrchr, (const wchar_t *, wchar_t)); size_t _EXFUN(wcsspn, (const wchar_t *, const wchar_t *)); @@ -119,15 +161,29 @@ wchar_t *_EXFUN(wcstok, (wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict)); double _EXFUN(wcstod, (const wchar_t *__restrict, wchar_t **__restrict)); double _EXFUN(_wcstod_r, (struct _reent *, const wchar_t *, wchar_t **)); +#if __ISO_C_VISIBLE >= 1999 float _EXFUN(wcstof, (const wchar_t *__restrict, wchar_t **__restrict)); +#endif float _EXFUN(_wcstof_r, (struct _reent *, const wchar_t *, wchar_t **)); #ifdef _LDBL_EQ_DBL long double _EXFUN(wcstold, (const wchar_t *, wchar_t **)); #endif /* _LDBL_EQ_DBL */ +#if __XSI_VISIBLE int _EXFUN(wcswidth, (const wchar_t *, size_t)); +#endif size_t _EXFUN(wcsxfrm, (wchar_t *__restrict, const wchar_t *__restrict, size_t)); +#if __POSIX_VISIBLE >= 200809 +extern int wcscasecmp_l (const wchar_t *, const wchar_t *, locale_t); +extern int wcsncasecmp_l (const wchar_t *, const wchar_t *, size_t, locale_t); +extern int wcscoll_l (const wchar_t *, const wchar_t *, locale_t); +extern size_t wcsxfrm_l (wchar_t *__restrict, const wchar_t *__restrict, size_t, + locale_t); +#endif + +#if __XSI_VISIBLE int _EXFUN(wcwidth, (const wchar_t)); +#endif wchar_t *_EXFUN(wmemchr, (const wchar_t *, wchar_t, size_t)); int _EXFUN(wmemcmp, (const wchar_t *, const wchar_t *, size_t)); wchar_t *_EXFUN(wmemcpy, (wchar_t *__restrict, const wchar_t *__restrict, @@ -136,26 +192,44 @@ wchar_t *_EXFUN(wmemmove, (wchar_t *, const wchar_t *, size_t)); wchar_t *_EXFUN(wmemset, (wchar_t *, wchar_t, size_t)); long _EXFUN(wcstol, (const wchar_t *__restrict, wchar_t **__restrict, int)); +#if __ISO_C_VISIBLE >= 1999 long long _EXFUN(wcstoll, (const wchar_t *__restrict, wchar_t **__restrict, int)); +#endif unsigned long _EXFUN(wcstoul, (const wchar_t *__restrict, wchar_t **__restrict, int)); +#if __ISO_C_VISIBLE >= 1999 unsigned long long _EXFUN(wcstoull, (const wchar_t *__restrict, wchar_t **__restrict, int)); +#endif long _EXFUN(_wcstol_r, (struct _reent *, const wchar_t *, wchar_t **, int)); long long _EXFUN(_wcstoll_r, (struct _reent *, const wchar_t *, wchar_t **, int)); unsigned long _EXFUN(_wcstoul_r, (struct _reent *, const wchar_t *, wchar_t **, int)); unsigned long long _EXFUN(_wcstoull_r, (struct _reent *, const wchar_t *, wchar_t **, int)); -/* On platforms where long double equals double. */ -#ifdef _LDBL_EQ_DBL +#if __ISO_C_VISIBLE >= 1999 long double _EXFUN(wcstold, (const wchar_t *, wchar_t **)); -#endif /* _LDBL_EQ_DBL */ +#endif + +#if __GNU_VISIBLE +long wcstol_l (const wchar_t *__restrict, wchar_t **__restrict, int, locale_t); +long long wcstoll_l (const wchar_t *__restrict, wchar_t **__restrict, int, + locale_t); +unsigned long wcstoul_l (const wchar_t *__restrict, wchar_t **__restrict, int, + locale_t); +unsigned long long wcstoull_l (const wchar_t *__restrict, wchar_t **__restrict, + int, locale_t); +double wcstod_l (const wchar_t *, wchar_t **, locale_t); +float wcstof_l (const wchar_t *, wchar_t **, locale_t); +long double wcstold_l (const wchar_t *, wchar_t **, locale_t); +#endif wint_t _EXFUN(fgetwc, (__FILE *)); wchar_t *_EXFUN(fgetws, (wchar_t *__restrict, int, __FILE *__restrict)); wint_t _EXFUN(fputwc, (wchar_t, __FILE *)); int _EXFUN(fputws, (const wchar_t *__restrict, __FILE *__restrict)); +#if __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE >= 500 int _EXFUN (fwide, (__FILE *, int)); +#endif wint_t _EXFUN (getwc, (__FILE *)); wint_t _EXFUN (getwchar, (void)); wint_t _EXFUN(putwc, (wchar_t, __FILE *)); @@ -192,7 +266,9 @@ wint_t _EXFUN(putwc_unlocked, (wchar_t, __FILE *)); wint_t _EXFUN(putwchar_unlocked, (wchar_t)); #endif +#if __POSIX_VISIBLE >= 200809 __FILE *_EXFUN (open_wmemstream, (wchar_t **, size_t *)); +#endif __FILE *_EXFUN (_open_wmemstream_r, (struct _reent *, wchar_t **, size_t *)); #ifndef __VALIST @@ -203,6 +279,7 @@ __FILE *_EXFUN (_open_wmemstream_r, (struct _reent *, wchar_t **, size_t *)); #endif #endif +#if __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE >= 500 int _EXFUN(fwprintf, (__FILE *__restrict, const wchar_t *__restrict, ...)); int _EXFUN(swprintf, (wchar_t *__restrict, size_t, const wchar_t *__restrict, ...)); @@ -212,6 +289,7 @@ int _EXFUN(vswprintf, (wchar_t *__restrict, size_t, const wchar_t *__restrict, __VALIST)); int _EXFUN(vwprintf, (const wchar_t *__restrict, __VALIST)); int _EXFUN(wprintf, (const wchar_t *__restrict, ...)); +#endif int _EXFUN(_fwprintf_r, (struct _reent *, __FILE *, const wchar_t *, ...)); int _EXFUN(_swprintf_r, (struct _reent *, wchar_t *, size_t, const wchar_t *, ...)); @@ -220,6 +298,7 @@ int _EXFUN(_vswprintf_r, (struct _reent *, wchar_t *, size_t, const wchar_t *, _ int _EXFUN(_vwprintf_r, (struct _reent *, const wchar_t *, __VALIST)); int _EXFUN(_wprintf_r, (struct _reent *, const wchar_t *, ...)); +#if __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE >= 500 int _EXFUN(fwscanf, (__FILE *__restrict, const wchar_t *__restrict, ...)); int _EXFUN(swscanf, (const wchar_t *__restrict, const wchar_t *__restrict, ...)); @@ -229,6 +308,7 @@ int _EXFUN(vswscanf, (const wchar_t *__restrict, const wchar_t *__restrict, __VALIST)); int _EXFUN(vwscanf, (const wchar_t *__restrict, __VALIST)); int _EXFUN(wscanf, (const wchar_t *__restrict, ...)); +#endif int _EXFUN(_fwscanf_r, (struct _reent *, __FILE *, const wchar_t *, ...)); int _EXFUN(_swscanf_r, (struct _reent *, const wchar_t *, const wchar_t *, ...)); diff --git a/libc/xtensa-lx106-elf/include/wctype.h b/libc/xtensa-lx106-elf/include/wctype.h index c72c9de..3d36d5a 100644 --- a/libc/xtensa-lx106-elf/include/wctype.h +++ b/libc/xtensa-lx106-elf/include/wctype.h @@ -7,6 +7,10 @@ #define __need_wint_t #include +#if __POSIX_VISIBLE >= 200809 +#include +#endif + #ifndef WEOF # define WEOF ((wint_t)-1) #endif @@ -25,7 +29,9 @@ typedef int wctrans_t; int _EXFUN(iswalpha, (wint_t)); int _EXFUN(iswalnum, (wint_t)); +#if __ISO_C_VISIBLE >= 1999 int _EXFUN(iswblank, (wint_t)); +#endif int _EXFUN(iswcntrl, (wint_t)); int _EXFUN(iswctype, (wint_t, wctype_t)); int _EXFUN(iswdigit, (wint_t)); @@ -42,6 +48,27 @@ wint_t _EXFUN(towlower, (wint_t)); wctrans_t _EXFUN(wctrans, (const char *)); wctype_t _EXFUN(wctype, (const char *)); +#if __POSIX_VISIBLE >= 200809 +extern int iswalpha_l (wint_t, locale_t); +extern int iswalnum_l (wint_t, locale_t); +extern int iswblank_l (wint_t, locale_t); +extern int iswcntrl_l (wint_t, locale_t); +extern int iswctype_l (wint_t, wctype_t, locale_t); +extern int iswdigit_l (wint_t, locale_t); +extern int iswgraph_l (wint_t, locale_t); +extern int iswlower_l (wint_t, locale_t); +extern int iswprint_l (wint_t, locale_t); +extern int iswpunct_l (wint_t, locale_t); +extern int iswspace_l (wint_t, locale_t); +extern int iswupper_l (wint_t, locale_t); +extern int iswxdigit_l (wint_t, locale_t); +extern wint_t towctrans_l (wint_t, wctrans_t, locale_t); +extern wint_t towupper_l (wint_t, locale_t); +extern wint_t towlower_l (wint_t, locale_t); +extern wctrans_t wctrans_l (const char *, locale_t); +extern wctype_t wctype_l (const char *, locale_t); +#endif + _END_STD_C #endif /* _WCTYPE_H_ */ diff --git a/libc/xtensa-lx106-elf/include/xlocale.h b/libc/xtensa-lx106-elf/include/xlocale.h new file mode 100644 index 0000000..f955426 --- /dev/null +++ b/libc/xtensa-lx106-elf/include/xlocale.h @@ -0,0 +1,12 @@ +/* Definition of opaque POSIX-1.2008 type locale_t for userspace. */ + +#ifndef _XLOCALE_H +#define _XLOCALE_H + +#include +#include + +struct __locale_t; +typedef struct __locale_t *locale_t; + +#endif /* _XLOCALE_H */ diff --git a/libc/xtensa-lx106-elf/lib/crt0.o b/libc/xtensa-lx106-elf/lib/crt0.o index 7d17e27..efc11bc 100644 Binary files a/libc/xtensa-lx106-elf/lib/crt0.o and b/libc/xtensa-lx106-elf/lib/crt0.o differ diff --git a/libc/xtensa-lx106-elf/lib/libc.a b/libc/xtensa-lx106-elf/lib/libc.a index a43b5ed..2c1132e 100644 Binary files a/libc/xtensa-lx106-elf/lib/libc.a and b/libc/xtensa-lx106-elf/lib/libc.a differ diff --git a/libc/xtensa-lx106-elf/lib/libg.a b/libc/xtensa-lx106-elf/lib/libg.a index 4d3d50a..2c1132e 100644 Binary files a/libc/xtensa-lx106-elf/lib/libg.a and b/libc/xtensa-lx106-elf/lib/libg.a differ diff --git a/libc/xtensa-lx106-elf/lib/libm.a b/libc/xtensa-lx106-elf/lib/libm.a index 2e9a859..2285786 100644 Binary files a/libc/xtensa-lx106-elf/lib/libm.a and b/libc/xtensa-lx106-elf/lib/libm.a differ diff --git a/lwip/component.mk b/lwip/component.mk index 1bbe21c..ea35d05 100644 --- a/lwip/component.mk +++ b/lwip/component.mk @@ -1,14 +1,12 @@ # Component makefile for LWIP LWIP_DIR = $(lwip_ROOT)lwip/src/ -INC_DIRS += $(LWIP_DIR)include $(ROOT)lwip/include $(lwip_ROOT)include $(LWIP_DIR)include/posix $(LWIP_DIR)include/ipv4 $(LWIP_DIR)include/ipv4/lwip $(LWIP_DIR)include/lwip +INC_DIRS += $(LWIP_DIR)include $(ROOT)lwip/include $(lwip_ROOT)include $(LWIP_DIR)include/compat/posix $(LWIP_DIR)include/ipv4 $(LWIP_DIR)include/ipv4/lwip $(LWIP_DIR)include/lwip # args for passing into compile rule generation lwip_INC_DIR = # all in INC_DIRS, needed for normal operation -lwip_SRC_DIR = $(lwip_ROOT) $(LWIP_DIR)api $(LWIP_DIR)core $(LWIP_DIR)core/ipv4 $(LWIP_DIR)netif - -# LWIP 1.4.1 generates a single warning so we need to disable -Werror when building it -lwip_CFLAGS = $(CFLAGS) -Wno-address +lwip_SRC_DIR = $(lwip_ROOT) $(LWIP_DIR)api $(LWIP_DIR)core $(LWIP_DIR)core/ipv4 $(LWIP_DIR)core/ipv6 $(LWIP_DIR)netif +lwip_SRC_DIR += $(LWIP_DIR)apps/* $(eval $(call component_compile_rules,lwip)) diff --git a/lwip/esp_interface.c b/lwip/esp_interface.c index 6f37b5a..77ad177 100644 --- a/lwip/esp_interface.c +++ b/lwip/esp_interface.c @@ -37,6 +37,7 @@ * Original Author: Simon Goldschmidt * Modified by Angus Gratton based on work by @kadamski/Espressif via esp-lwip project. */ +#include #include "lwip/opt.h" #include "lwip/def.h" @@ -44,77 +45,259 @@ #include "lwip/pbuf.h" #include #include +#include "lwip/ip.h" +#include "lwip/ethip6.h" +#include "lwip/priv/tcp_priv.h" #include "netif/etharp.h" +#include "sysparam.h" +#include "netif/ppp/pppoe.h" +#include "FreeRTOS.h" +#include "task.h" /* declared in libnet80211.a */ int8_t sdk_ieee80211_output_pbuf(struct netif *ifp, struct pbuf* pb); +/* Define those to better describe your network interface. */ +#define IFNAME0 'e' +#define IFNAME1 'n' + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void +low_level_init(struct netif *netif) +{ + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6; + + /* Do whatever else is needed to initialize interface. */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) static err_t low_level_output(struct netif *netif, struct pbuf *p) { - struct pbuf *q; + /* + * Note the pbuf reference count is generally one here, but not always. For + * example a buffer that had been queued by etharp_query() would have had + * its reference count increased to two, and the caller will free it on that + * return path. + */ - for(q = p; q != NULL; q = q->next) { - sdk_ieee80211_output_pbuf(netif, q); - } + /* If the pbuf does not have contiguous data, or there is not enough room + * for the link layer header, or there are multiple pbufs in the chain then + * clone a pbuf to output. */ + if ((p->type_internal & PBUF_TYPE_FLAG_STRUCT_DATA_CONTIGUOUS) == 0 || + (u8_t *)p->payload < (u8_t *)p + SIZEOF_STRUCT_PBUF + PBUF_LINK_ENCAPSULATION_HLEN || + p->next) { + struct pbuf *q = pbuf_clone(PBUF_RAW_TX, PBUF_RAM, p); + if (q == NULL) { + return ERR_MEM; + } + sdk_ieee80211_output_pbuf(netif, q); + /* The sdk will pbuf_ref the pbuf before returning and free it later + * when it has been sent so free the link to it here. */ + pbuf_free(q); + } else { + /* The SDK modifies the eth_hdr, well the first 12 bytes of it at least, + * but otherwise leaves the payload unmodified so it can be reused by + * the caller. The only paths that appear to reuse the pbuf are in + * tcp_out for re-transmission of TCP segments, and these paths check + * that the number of references has returned to one before reusing the + * pbuf. + */ + sdk_ieee80211_output_pbuf(netif, p); + } - LINK_STATS_INC(link.xmit); - - return ERR_OK; + LINK_STATS_INC(link.xmit); + return ERR_OK; } -err_t ethernetif_init(struct netif *netif) +/** + * Keep account of the number the PP RX pool buffers being used in lwip, + * to help make decision about the number of OOSEQ buffers to maintain etc. + */ +volatile uint32_t pp_rx_pool_usage; + +/* Support for recycling a pbuf from the sdk rx pool, and accounting for the + * number of these used in lwip. */ +void pp_recycle_rx_pbuf(struct pbuf *p) { - LWIP_ASSERT("netif != NULL", (netif != NULL)); - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwip"; -#endif /* LWIP_NETIF_HOSTNAME */ - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); - - // don't touch netif->state here, the field is used internally in the ESP SDK layers - netif->name[0] = 'e'; - netif->name[1] = 'n'; - netif->output = etharp_output; - netif->linkoutput = low_level_output; - - /* low_level_init components */ - netif->hwaddr_len = 6; - /* hwaddr seems to be set elsewhere, or (more likely) is set on tx by MAC layer */ - netif->mtu = 1500; - netif->flags = NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - - return ERR_OK; + LWIP_ASSERT("expected esf_buf", p->esf_buf); + sdk_system_pp_recycle_rx_pkt(p->esf_buf); + taskENTER_CRITICAL(); + LWIP_ASSERT("pp_rx_pool_usage underflow", pp_rx_pool_usage > 0); + pp_rx_pool_usage--; + taskEXIT_CRITICAL(); } +/* Set to true to copy the rx pbufs on input and free them. The pp rx buffer + * pool is limited so this allows a large number at the expense of memory. + */ + +#define COPY_PP_RX_PBUFS 0 + +#if TCP_QUEUE_OOSEQ + +/* Return the number of ooseq bytes that can be retained given the current + * size 'n'. */ +size_t ooseq_bytes_limit(struct tcp_pcb *pcb) +{ +#if COPY_PP_RX_PBUFS + struct tcp_seg *ooseq = pcb->ooseq; + size_t ooseq_blen = 0; + for (; ooseq != NULL; ooseq = ooseq->next) { + struct pbuf *p = ooseq->p; + ooseq_blen += p->tot_len; + } + + size_t free = xPortGetFreeHeapSize(); + ssize_t target = ((ssize_t)free - 8000) + ooseq_blen; + + if (target < 0) { + target = 0; + } + + return target; +#else + /* The pool is pre-allocated so there is no need to look at the dynamic + * memory usage, just consider the number of them below. */ + return 8000; +#endif +} + +/* Return the number of ooseq pbufs that can be retained given the current + * size 'n'. */ +size_t ooseq_pbufs_limit(struct tcp_pcb *pcb) +{ + struct tcp_seg *ooseq = pcb->ooseq; + size_t ooseq_qlen = 0; + for (; ooseq != NULL; ooseq = ooseq->next) { + struct pbuf *p = ooseq->p; + ooseq_qlen += pbuf_clen(p); + } + +#if COPY_PP_RX_PBUFS + /* More likely memory limited, but set some limit. */ + ssize_t limit = 10; +#else + /* Set a small limit if using the pp rx pool, to avoid exhausting it. */ + ssize_t limit = 2; +#endif + + size_t usage = pp_rx_pool_usage; + ssize_t target = limit - ((ssize_t)usage - ooseq_qlen); + + if (target < 0) { + target = 0; + } + + return target; +} + +#endif /* TCP_QUEUE_OOSEQ */ + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ /* called from ieee80211_deliver_data with new IP frames */ void ethernetif_input(struct netif *netif, struct pbuf *p) { - struct eth_hdr *ethhdr = p->payload; - /* examine packet payloads ethernet header */ + struct eth_hdr *ethhdr; + if (p == NULL) { + return; + } + + if (p->payload == NULL) { + return; + } + + if (netif == NULL) { + return; + } + + ethhdr = p->payload; + + /* Account for the number of rx pool buffers being used. */ + taskENTER_CRITICAL(); + uint32_t usage = pp_rx_pool_usage + 1; + pp_rx_pool_usage = usage; + taskEXIT_CRITICAL(); switch(htons(ethhdr->type)) { /* IP or ARP packet? */ case ETHTYPE_IP: + case ETHTYPE_IPV6: +#if 0 + /* Simulate IP packet loss. */ + if ((random() & 0xff) < 0x10) { + pbuf_free(p); + return; + } +#endif + case ETHTYPE_ARP: -// case ETHTYPE_IPV6: +#if PPPOE_SUPPORT + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + { /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif)!=ERR_OK) - { + +#if COPY_PP_RX_PBUFS + /* Optionally copy the rx pool buffer and free it immediately. This + * helps avoid exhausting the limited rx buffer pool but uses more + * memory. */ + struct pbuf *q = pbuf_clone(PBUF_RAW, PBUF_RAM, p); + pbuf_free(p); + if (q == NULL) { + return; + } + p = q; +#endif + + if (netif->input(p, netif) != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); pbuf_free(p); p = NULL; } break; + } default: pbuf_free(p); @@ -122,3 +305,98 @@ void ethernetif_input(struct netif *netif, struct pbuf *p) break; } } + +/* Since the pbuf_type definition has changed in lwip v2 and it is used by the + * sdk when calling pbuf_alloc, the SDK libraries have been modified to rename + * their references to pbuf_alloc to _pbufalloc allowing the pbuf_type to be + * rewritten here. Doing this here keeps this hack out of the lwip code, and + * ensures that this re-writing is only applied to the sdk calls to pbuf_alloc. + * + * The only pbuf types used by the SDK are type 0 for PBUF_RAM when writing + * data, and type 2 for the received data. The receive data path references + * internal buffer objects that need to be freed with custom code so a custom + * pbuf allocation type is used for these. + * + * The pbuf_layer is now also the header offset, but the sdk calls only call + * with a value of 3 which was PBUF_RAW and is now translated to a header + * offset of zero. + */ +struct pbuf *sdk_pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) { + if (type == 0) { + LWIP_ASSERT("Unexpected sdk_pbuf_alloc layer", layer == 3 || layer == 4); + return pbuf_alloc(PBUF_RAW_TX, length, PBUF_RAM); + } else if (type == 2) { + LWIP_ASSERT("Unexpected sdk_pbuf_alloc layer", layer == 3); + return pbuf_alloc_reference(NULL, length, PBUF_ALLOC_FLAG_RX | PBUF_TYPE_ALLOC_SRC_MASK_ESP_RX); + } else { + LWIP_ASSERT("Unexpected pbuf_alloc type", 0); + for (;;); + } +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t +ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + /* The hwaddr is currently set by sdk_wifi_station_start or + * sdk_wifi_softap_start. */ + +#if LWIP_IPV6 + // Where to do this??? + netif_create_ip6_linklocal_address(netif, 1); + netif->ip6_autoconfig_enabled = 1; + printf("ip6 link local address %s\n", ip6addr_ntoa(netif_ip6_addr(netif, 0))); +#endif + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + char *hostname = NULL; + /* Disabled for now as there were reports of crashes here, sysparam issues */ + /* sysparam_get_string("hostname", &hostname); */ + if (hostname && strlen(hostname) == 0) { + free(hostname); + hostname = NULL; + } + netif->hostname = hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + // don't touch netif->state here, the field is used internally in the ESP SDK layers + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ +#if LWIP_IPV4 + netif->output = etharp_output; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} diff --git a/lwip/include/arch/cc.h b/lwip/include/arch/cc.h index 2922a54..e7cf291 100644 --- a/lwip/include/arch/cc.h +++ b/lwip/include/arch/cc.h @@ -32,36 +32,25 @@ #ifndef __ARCH_CC_H__ #define __ARCH_CC_H__ -/* include ESP SDK prototypes as they're used in some LWIP routines */ -#include "espressif/sdk_private.h" - -/* ESP8266 SDK Interface - - The lwip-esp stack is designed to be also compatible with other ESP8266 SDKs, - so we can't use our 'sdk_' prefixes there -*/ -#define system_station_got_ip_set sdk_system_station_got_ip_set -#define system_pp_recycle_rx_pkt sdk_system_pp_recycle_rx_pkt - /* Include some files for defining library routines */ #include /* printf, fflush, FILE */ #include /* abort */ #include #include #include +#include -#define ERRNO +struct ip4_addr; +struct esf_buf; +void sdk_system_station_got_ip_set(struct ip4_addr *, struct ip4_addr *, struct ip4_addr *); +void sdk_system_pp_recycle_rx_pkt(struct esf_buf *); -#define BYTE_ORDER LITTLE_ENDIAN +struct pbuf; +void pp_recycle_rx_pbuf(struct pbuf *); -/** @todo fix some warnings: don't use #pragma if compiling with cygwin gcc */ -#ifndef __GNUC__ - #include - #pragma warning (disable: 4244) /* disable conversion warning (implicit integer promotion!) */ - #pragma warning (disable: 4127) /* conditional expression is constant */ - #pragma warning (disable: 4996) /* 'strncpy' was declared deprecated */ - #pragma warning (disable: 4103) /* structure packing changed by including file */ -#endif +struct tcp_pcb; +size_t ooseq_bytes_limit(struct tcp_pcb *); +size_t ooseq_pbufs_limit(struct tcp_pcb *); /* Define generic types used in lwIP */ typedef uint8_t u8_t; @@ -112,4 +101,6 @@ typedef int sys_prot_t; #define LWIP_PLATFORM_HTONS(_n) ((u16_t)((((_n) & 0xff) << 8) | (((_n) >> 8) & 0xff))) #define LWIP_PLATFORM_HTONL(_n) ((u32_t)( (((_n) & 0xff) << 24) | (((_n) & 0xff00) << 8) | (((_n) >> 8) & 0xff00) | (((_n) >> 24) & 0xff) )) +#define LWIP_RAND() hwrand() + #endif /* __ARCH_CC_H__ */ diff --git a/lwip/include/lwipopts.h b/lwip/include/lwipopts.h index 8f46c7d..4d69eda 100644 --- a/lwip/include/lwipopts.h +++ b/lwip/include/lwipopts.h @@ -32,11 +32,15 @@ #ifndef __LWIPOPTS_H__ #define __LWIPOPTS_H__ -#define LWIP_ESP 1 -#define ESP_RTOS 1 -#define PBUF_RSV_FOR_WLAN 1 -#define EBUF_LWIP 1 +#define ESP_OPEN_RTOS 1 + +/* See tcp.c tcp_alloc(). */ +#ifndef ESP_TIMEWAIT_THRESHOLD #define ESP_TIMEWAIT_THRESHOLD 10000 +#endif + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ #define LWIP_TIMEVAL_PRIVATE 0 /* @@ -63,6 +67,34 @@ */ #define SMEMCPY(dst,src,len) memcpy(dst,src,len) +/* + ------------------------------------ + ----------- Core locking ----------- + ------------------------------------ +*/ + +/** + * LWIP_TCPIP_CORE_LOCKING + * Creates a global mutex that is held during TCPIP thread operations. + * Can be locked by client code to perform lwIP operations without changing + * into TCPIP thread using callbacks. See LOCK_TCPIP_CORE() and + * UNLOCK_TCPIP_CORE(). + * Your system should provide mutexes supporting priority inversion to use this. + */ +#define LWIP_TCPIP_CORE_LOCKING 1 + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: when LWIP_TCPIP_CORE_LOCKING is enabled, + * this lets tcpip_input() grab the mutex for input packets as well, + * instead of allocating a message and passing it to tcpip_thread. + * + * ATTENTION: this does not work when tcpip_input() is called from + * interrupt context! + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + /* ------------------------------------ ---------- Memory options ---------- @@ -76,19 +108,36 @@ #define MEM_LIBC_MALLOC 1 /** -* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. -* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution -* speed and usage from interrupts! -*/ + * MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. + * Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution + * speed (heap alloc can be much slower than pool alloc) and usage from interrupts + * (especially if your netif driver allocates PBUF_POOL pbufs for received frames + * from interrupt)! + * ATTENTION: Currently, this uses the heap for ALL pools (also for private pools, + * not only for internal pools defined in memp_std.h)! + */ #define MEMP_MEM_MALLOC 1 /** * MEM_ALIGNMENT: should be set to the alignment of the CPU - * 4 byte alignment -> #define MEM_ALIGNMENT 4 - * 2 byte alignment -> #define MEM_ALIGNMENT 2 + * 4 byte alignment -> \#define MEM_ALIGNMENT 4 + * 2 byte alignment -> \#define MEM_ALIGNMENT 2 */ #define MEM_ALIGNMENT 4 +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + /* ------------------------------------------------ ---------- Internal Memory Pool Sizes ---------- @@ -100,6 +149,14 @@ ---------- ARP options ------- -------------------------------- */ + +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + /** * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address * resolution. By default, only the most recent packet is queued per IP address. @@ -107,7 +164,9 @@ * startup time. Set this to 1 if you know your application sends more than one * packet in a row to an IP address that is not in the ARP cache. */ +#ifndef ARP_QUEUEING #define ARP_QUEUEING 1 +#endif /* -------------------------------- @@ -119,21 +178,27 @@ * this option does not affect outgoing packet sizes, which can be controlled * via IP_FRAG. */ -#define IP_REASSEMBLY 0 +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 1 +#endif /** * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note * that this option does not affect incoming packet sizes, which can be * controlled via IP_REASSEMBLY. */ +#ifndef IP_FRAG #define IP_FRAG 1 +#endif /** * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived * in this time, the whole packet is discarded. */ +#ifndef IP_REASS_MAXAGE #define IP_REASS_MAXAGE 3 +#endif /** * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. @@ -141,7 +206,9 @@ * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive * packets even if the maximum amount of fragments is enqueued for reassembly! */ -#define IP_REASS_MAX_PBUFS 10 +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 2 +#endif /* ---------------------------------- @@ -163,7 +230,16 @@ /** * LWIP_DHCP==1: Enable DHCP module. */ +#ifndef LWIP_DHCP #define LWIP_DHCP 1 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif #define LWIP_DHCP_BOOTP_FILE 0 @@ -174,14 +250,21 @@ */ /* ---------------------------------- - ---------- SNMP options ---------- + ----- SNMP MIB2 support ----- ---------------------------------- */ /* ---------------------------------- - ---------- IGMP options ---------- + ----- Multicast/IGMP options ----- ---------------------------------- */ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 1 +#endif + /* ---------------------------------- ---------- DNS options ----------- @@ -191,10 +274,19 @@ * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS * transport. */ +#ifndef LWIP_DNS #define LWIP_DNS 1 +#endif +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE #define DNS_TABLE_SIZE 1 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH #define DNS_MAX_NAME_LENGTH 128 +#endif /* --------------------------------- @@ -206,30 +298,131 @@ ---------- TCP options ---------- --------------------------------- */ -/** - * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. - * Define to 0 if your device is low on memory. - */ -#define TCP_QUEUE_OOSEQ 0 - -/* - * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all - * events (accept, sent, etc) that happen in the system. - * LWIP_CALLBACK_API==1: The PCB callback function is called directly - * for the event. This is the default. -*/ -#define TCP_MSS 1460 - /** * TCP_MAXRTX: Maximum number of retransmissions of data segments. */ +#ifndef TCP_MAXRTX #define TCP_MAXRTX 6 - +#endif /** * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. */ +#ifndef TCP_SYNMAXRTX #define TCP_SYNMAXRTX 3 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ 1 +#endif + +/** + * LWIP_TCP_SACK_OUT==1: TCP will support sending selective acknowledgements (SACKs). + */ +#ifndef LWIP_TCP_SACK_OUT +#define LWIP_TCP_SACK_OUT 1 +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 1460 +#endif + +/** + * TCP_OOSEQ_MAX_BYTES: The default maximum number of bytes queued on ooseq per + * pcb if TCP_OOSEQ_BYTES_LIMIT is not defined. Default is 0 (no limit). + * Only valid for TCP_QUEUE_OOSEQ==1. + */ +#ifndef TCP_OOSEQ_MAX_BYTES +#define TCP_OOSEQ_MAX_BYTES (2 * TCP_MSS) +#endif + +/** + * TCP_OOSEQ_BYTES_LIMIT(ooseq): Return the maximum number of bytes to be queued + * on ooseq per pcb, given the pcb. Only valid for TCP_QUEUE_OOSEQ==1. + */ +#if !defined TCP_OOSEQ_BYTES_LIMIT +#define TCP_OOSEQ_BYTES_LIMIT(ooseq) ooseq_bytes_limit(ooseq) +#endif + +/** + * TCP_OOSEQ_MAX_PBUFS: The default maximum number of pbufs queued on ooseq per + * pcb if TCP_OOSEQ_BYTES_LIMIT is not defined. Default is 0 (no limit). + * Only valid for TCP_QUEUE_OOSEQ==1. + */ +#ifndef TCP_OOSEQ_MAX_PBUFS +#define TCP_OOSEQ_MAX_PBUFS 2 +#endif + +/** + * TCP_OOSEQ_PBUFS_LIMIT(ooseq): Return the maximum number of pbufs to be queued + * on ooseq per pcb, given the pcb. Only valid for TCP_QUEUE_OOSEQ==1. + */ +#ifndef TCP_OOSEQ_PBUFS_LIMIT +#define TCP_OOSEQ_PBUFS_LIMIT(ooseq) ooseq_pbufs_limit(ooseq) +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 1 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 2 +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + * The timestamp option is currently only used to help remote hosts, it is not + * really used locally. Therefore, it is only enabled when a TS option is + * received in the initial SYN packet from a remote host. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 1 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) +#endif /* ---------------------------------- @@ -237,19 +430,50 @@ ---------------------------------- */ +/** + * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated + * for an additional encapsulation header before ethernet headers (e.g. 802.11) + * + * 1. LINK_HLEN 14Byte will be remove in WLAN layer + * 2. IEEE80211_HDR_MAX_LEN needs 40 bytes. + * 3. encryption needs exra 4 bytes ahead of actual data payload, and require + * DAddr and SAddr to be 4-byte aligned. + * 4. TRANSPORT and IP are all 20, 4 bytes aligned, nice... + * 5. LCC add 6 bytes more, We don't consider WAPI yet... + * 6. define LWIP_MEM_ALIGN to be 4 Byte aligned, pbuf struct is 16B, Only thing may be + * matter is ether_hdr is not 4B aligned. + * + * So, we need extra (40 + 4 - 14) = 30 and it's happen to be 4-Byte aligned + * + * 1. lwip + * | empty 30B | eth_hdr (14B) | payload ...| + * total: 44B ahead payload + * 2. net80211 + * | max 80211 hdr, 32B | ccmp/tkip iv (8B) | sec rsv(4B) | payload ...| + * total: 40B ahead sec_rsv and 44B ahead payload + * + */ +#define PBUF_LINK_ENCAPSULATION_HLEN 36 + /* ------------------------------------------------ ---------- Network Interfaces options ---------- ------------------------------------------------ */ /** - * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP *tries* to put all data * to be sent into one single pbuf. This is for compatibility with DMA-enabled * MACs that do not support scatter-gather. * Beware that this might involve CPU-memcpy before transmitting that would not * be needed without this flag! Use this only if you need to! - * - * @todo: TCP and IP-frag do not work with this, yet: */ #define LWIP_NETIF_TX_SINGLE_PBUF 1 @@ -275,7 +499,9 @@ * The stack size value itself is platform-dependent, but is passed to * sys_thread_new() when the thread is created. */ -#define TCPIP_THREAD_STACKSIZE 512 //not ok:384 +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 768 +#endif /** * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. @@ -327,30 +553,40 @@ * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and * SO_SNDTIMEO processing. */ +#ifndef LWIP_SO_SNDTIMEO #define LWIP_SO_SNDTIMEO 1 +#endif /** * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and * SO_RCVTIMEO processing. */ +#ifndef LWIP_SO_RCVTIMEO #define LWIP_SO_RCVTIMEO 1 +#endif /** * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set * in seconds. (does not require sockets.c, and will affect tcp.c) */ +#ifndef LWIP_TCP_KEEPALIVE #define LWIP_TCP_KEEPALIVE 1 +#endif /** * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. */ +#ifndef LWIP_SO_RCVBUF #define LWIP_SO_RCVBUF 0 +#endif /** * SO_REUSE==1: Enable SO_REUSEADDR option. */ +#ifndef SO_REUSE #define SO_REUSE 1 +#endif /* ---------------------------------------- @@ -358,6 +594,20 @@ ---------------------------------------- */ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + /* --------------------------------- ---------- PPP options ---------- @@ -375,6 +625,12 @@ ---------- IPv6 options --------------- --------------------------------------- */ +/** + * LWIP_IPV6==1: Enable IPv6 + */ +#ifndef LWIP_IPV6 +#define LWIP_IPV6 0 +#endif /* --------------------------------------- @@ -391,11 +647,29 @@ // Uncomment this line, and set the individual debug options you want, for IP stack debug output //#define LWIP_DEBUG +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +//#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_WARNING + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON + /** * ETHARP_DEBUG: Enable debugging in etharp.c. */ #define ETHARP_DEBUG LWIP_DBG_OFF +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#define NETIF_DEBUG LWIP_DBG_OFF + /** * PBUF_DEBUG: Enable debugging in pbuf.c. */ @@ -406,50 +680,151 @@ */ #define API_LIB_DEBUG LWIP_DBG_OFF +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#define API_MSG_DEBUG LWIP_DBG_OFF + /** * SOCKETS_DEBUG: Enable debugging in sockets.c. */ #define SOCKETS_DEBUG LWIP_DBG_OFF +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#define ICMP_DEBUG LWIP_DBG_OFF + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#define IGMP_DEBUG LWIP_DBG_OFF + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#define INET_DEBUG LWIP_DBG_OFF + /** * IP_DEBUG: Enable debugging for IP. */ #define IP_DEBUG LWIP_DBG_OFF +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#define IP_REASS_DEBUG LWIP_DBG_OFF + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#define RAW_DEBUG LWIP_DBG_OFF + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#define MEM_DEBUG LWIP_DBG_OFF + /** * MEMP_DEBUG: Enable debugging in memp.c. */ #define MEMP_DEBUG LWIP_DBG_OFF +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#define SYS_DEBUG LWIP_DBG_OFF + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#define TIMERS_DEBUG LWIP_DBG_OFF + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#define TCP_DEBUG LWIP_DBG_OFF + /** * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. */ #define TCP_INPUT_DEBUG LWIP_DBG_OFF +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#define TCP_FR_DEBUG LWIP_DBG_OFF + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#define TCP_RTO_DEBUG LWIP_DBG_OFF + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#define TCP_CWND_DEBUG LWIP_DBG_OFF + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#define TCP_WND_DEBUG LWIP_DBG_OFF + /** * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. */ #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF /** - * UDP_DEBUG: Enable debugging in udp.c. + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. */ -#define UDP_DEBUG LWIP_DBG_OFF +#define TCP_RST_DEBUG LWIP_DBG_OFF /** - * ICMP_DEBUG: Enable debugging in udp.c. + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. */ -#define ICMP_DEBUG LWIP_DBG_OFF +#define TCP_QLEN_DEBUG LWIP_DBG_OFF + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#define UDP_DEBUG LWIP_DBG_OFF /** * TCPIP_DEBUG: Enable debugging in tcpip.c. */ #define TCPIP_DEBUG LWIP_DBG_OFF +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#define SLIP_DEBUG LWIP_DBG_OFF /** * DHCP_DEBUG: Enable debugging in dhcp.c. */ #define DHCP_DEBUG LWIP_DBG_OFF +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#define AUTOIP_DEBUG LWIP_DBG_OFF + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#define DNS_DEBUG LWIP_DBG_OFF + +/** + * IP6_DEBUG: Enable debugging for IPv6. + */ +#define IP6_DEBUG LWIP_DBG_OFF + +/* + -------------------------------------------------- + ---------- Performance tracking options ---------- + -------------------------------------------------- +*/ + #endif /* __LWIPOPTS_H__ */ diff --git a/lwip/lwip b/lwip/lwip index 3cf8d51..74676d4 160000 --- a/lwip/lwip +++ b/lwip/lwip @@ -1 +1 @@ -Subproject commit 3cf8d514bd76e6ef77e6fa514d0ec6d96da7fd9a +Subproject commit 74676d46f0bc5ed82515f8e247008b7c45ec6cf6 diff --git a/lwip/sys_arch.c b/lwip/sys_arch.c index 87d8450..1a9c5f9 100644 --- a/lwip/sys_arch.c +++ b/lwip/sys_arch.c @@ -49,17 +49,147 @@ #include "lwip/mem.h" #include "lwip/stats.h" -extern bool esp_in_isr; - -/* Based on the default xInsideISR mechanism to determine - if an ISR is running. - - Doesn't support the possibility that LWIP functions are called from the NMI - handler (none are called from NMI when using current/SDK implementation.) -*/ -static inline bool is_inside_isr() +/*---------------------------------------------------------------------------* + * Routine: sys_sem_new + *---------------------------------------------------------------------------* + * Description: + * Creates and returns a new semaphore. The "ucCount" argument specifies + * the initial state of the semaphore. + * NOTE: Currently this routine only creates counts of 1 or 0 + * Inputs: + * sys_mbox_t mbox -- Handle of mailbox + * u8_t ucCount -- Initial ucCount of semaphore (1 or 0) + * Outputs: + * sys_sem_t -- Created semaphore or 0 if could not create. + *---------------------------------------------------------------------------*/ +err_t sys_sem_new(sys_sem_t *pxSemaphore, u8_t ucCount) { - return esp_in_isr; + err_t xReturn = ERR_MEM; + + vSemaphoreCreateBinary(*pxSemaphore); + + if (*pxSemaphore != NULL) { + if (ucCount == 0U) { + xSemaphoreTake(*pxSemaphore, 1UL); + } + + xReturn = ERR_OK; + SYS_STATS_INC_USED(sem); + } else { + SYS_STATS_INC(sem.err); + } + + return xReturn; +} + +/*---------------------------------------------------------------------------* + * Routine: sys_sem_free + *---------------------------------------------------------------------------* + * Description: + * Deallocates a semaphore + * Inputs: + * sys_sem_t sem -- Semaphore to free + *---------------------------------------------------------------------------*/ +void sys_sem_free(sys_sem_t *pxSemaphore) +{ + SYS_STATS_DEC(sem.used); + vQueueDelete(*pxSemaphore); +} + +/*---------------------------------------------------------------------------* + * Routine: sys_sem_signal + *---------------------------------------------------------------------------* + * Description: + * Signals (releases) a semaphore + * Inputs: + * sys_sem_t sem -- Semaphore to signal + *---------------------------------------------------------------------------*/ +void sys_sem_signal(sys_sem_t *pxSemaphore) +{ + xSemaphoreGive(*pxSemaphore); +} + +/*---------------------------------------------------------------------------* + * Routine: sys_arch_sem_wait + *---------------------------------------------------------------------------* + * Description: + + * Blocks the thread while waiting for the semaphore to be signaled. If the + * "timeout" argument is non-zero, the thread should only be blocked for + * the specified time (measured in milliseconds). If the "timeout" argument + * is zero, the thread should be blocked until the semaphore is signalled. + * + * The return value is SYS_ARCH_TIMEOUT if the semaphore wasn't signaled + * within the specified time or any other value if it was signaled (with or + * without waiting). + * + * Notice that lwIP implements a function with a similar name, + * sys_sem_wait(), that uses the sys_arch_sem_wait() function. + * Inputs: + * sys_sem_t sem -- Semaphore to wait on + * u32_t timeout -- Number of milliseconds until timeout + * Outputs: + * u32_t -- SYS_ARCH_TIMEOUT on timeout, any other value on success + *---------------------------------------------------------------------------*/ +u32_t sys_arch_sem_wait(sys_sem_t *pxSemaphore, u32_t ulTimeout) +{ + u32_t ulReturn; + + if (ulTimeout != 0UL) { + if (xSemaphoreTake(*pxSemaphore, ulTimeout / portTICK_PERIOD_MS) == pdTRUE) { + ulReturn = 0; + } else { + ulReturn = SYS_ARCH_TIMEOUT; + } + } else { + while (xSemaphoreTake(*pxSemaphore, portMAX_DELAY) != pdTRUE); + ulReturn = 0; + } + + return ulReturn; +} + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *pxMutex) +{ + err_t xReturn; + + *pxMutex = xSemaphoreCreateMutex(); + + if (*pxMutex != NULL) { + xReturn = ERR_OK; + SYS_STATS_INC_USED(mutex); + } else { + xReturn = ERR_MEM; + SYS_STATS_INC(mutex.err); + } + + return xReturn; +} + +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *pxMutex) +{ + while (xSemaphoreTake(*pxMutex, portMAX_DELAY) != pdPASS); +} + +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *pxMutex) +{ + xSemaphoreGive(*pxMutex); +} + + +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *pxMutex) +{ + SYS_STATS_DEC(mutex.used); + vQueueDelete(*pxMutex); } /*---------------------------------------------------------------------------* @@ -72,16 +202,15 @@ static inline bool is_inside_isr() * Outputs: * sys_mbox_t -- Handle to new mailbox *---------------------------------------------------------------------------*/ -err_t sys_mbox_new( sys_mbox_t *pxMailBox, int iSize ) +err_t sys_mbox_new(sys_mbox_t *pxMailBox, int iSize) { err_t xReturn = ERR_MEM; - *pxMailBox = xQueueCreate( iSize, sizeof( void * ) ); + *pxMailBox = xQueueCreate(iSize, sizeof(void *)); - if( *pxMailBox != NULL ) - { + if (*pxMailBox != NULL) { xReturn = ERR_OK; - SYS_STATS_INC_USED( mbox ); + SYS_STATS_INC_USED(mbox); } return xReturn; @@ -100,25 +229,24 @@ err_t sys_mbox_new( sys_mbox_t *pxMailBox, int iSize ) * Outputs: * sys_mbox_t -- Handle to new mailbox *---------------------------------------------------------------------------*/ -void sys_mbox_free( sys_mbox_t *pxMailBox ) +void sys_mbox_free(sys_mbox_t *pxMailBox) { -unsigned long ulMessagesWaiting; + unsigned long ulMessagesWaiting; - ulMessagesWaiting = uxQueueMessagesWaiting( *pxMailBox ); - configASSERT( ( ulMessagesWaiting == 0 ) ); + ulMessagesWaiting = uxQueueMessagesWaiting(*pxMailBox); + configASSERT(ulMessagesWaiting == 0); #if SYS_STATS { - if( ulMessagesWaiting != 0UL ) - { - SYS_STATS_INC( mbox.err ); + if (ulMessagesWaiting != 0UL) { + SYS_STATS_INC(mbox.err); } - SYS_STATS_DEC( mbox.used ); + SYS_STATS_DEC(mbox.used); } #endif /* SYS_STATS */ - vQueueDelete( *pxMailBox ); + vQueueDelete(*pxMailBox); } /*---------------------------------------------------------------------------* @@ -130,9 +258,9 @@ unsigned long ulMessagesWaiting; * sys_mbox_t mbox -- Handle of mailbox * void *data -- Pointer to data to post *---------------------------------------------------------------------------*/ -void sys_mbox_post( sys_mbox_t *pxMailBox, void *pxMessageToPost ) +void sys_mbox_post(sys_mbox_t *pxMailBox, void *pxMessageToPost) { - while( xQueueSendToBack( *pxMailBox, &pxMessageToPost, portMAX_DELAY ) != pdTRUE ); + while (xQueueSendToBack(*pxMailBox, &pxMessageToPost, portMAX_DELAY) != pdTRUE); } /*---------------------------------------------------------------------------* @@ -148,26 +276,13 @@ void sys_mbox_post( sys_mbox_t *pxMailBox, void *pxMessageToPost ) * err_t -- ERR_OK if message posted, else ERR_MEM * if not. *---------------------------------------------------------------------------*/ -err_t sys_mbox_trypost( sys_mbox_t *pxMailBox, void *pxMessageToPost ) +err_t sys_mbox_trypost(sys_mbox_t *pxMailBox, void *pxMessageToPost) { -err_t xReturn; -portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + err_t xReturn; - if( is_inside_isr() != pdFALSE ) - { - xReturn = xQueueSendFromISR( *pxMailBox, &pxMessageToPost, &xHigherPriorityTaskWoken ); - } - else - { - xReturn = xQueueSend( *pxMailBox, &pxMessageToPost, ( TickType_t ) 0 ); - } - - if( xReturn == pdPASS ) - { + if (xQueueSend(*pxMailBox, &pxMessageToPost, 0)) { xReturn = ERR_OK; - } - else - { + } else { /* The queue was already full. */ xReturn = ERR_MEM; SYS_STATS_INC( mbox.err ); @@ -188,8 +303,8 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; * should be dropped. * * The return values are the same as for the sys_arch_sem_wait() function: - * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a - * timeout. + * SYS_ARCH_TIMEOUT if there was a timeout, any other value if a messages + * is received. * * Note that a function with a similar name, sys_mbox_fetch(), is * implemented by lwIP. @@ -198,52 +313,28 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; * void **msg -- Pointer to pointer to msg received * u32_t timeout -- Number of milliseconds until timeout * Outputs: - * u32_t -- SYS_ARCH_TIMEOUT if timeout, else number - * of milliseconds until received. + * u32_t -- SYS_ARCH_TIMEOUT on timeout, any other value if a message has been received *---------------------------------------------------------------------------*/ -u32_t sys_arch_mbox_fetch( sys_mbox_t *pxMailBox, void **ppvBuffer, u32_t ulTimeOut ) +u32_t sys_arch_mbox_fetch(sys_mbox_t *pxMailBox, void **ppvBuffer, u32_t ulTimeOut) { -void *pvDummy; -TickType_t xStartTime, xEndTime, xElapsed; -unsigned long ulReturn; + void *pvDummy; + unsigned long ulReturn; - xStartTime = xTaskGetTickCount(); - - if( NULL == ppvBuffer ) - { + if (ppvBuffer == NULL) { ppvBuffer = &pvDummy; } - if( ulTimeOut != 0UL ) - { - configASSERT( is_inside_isr() == ( portBASE_TYPE ) 0 ); - - if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), ulTimeOut/ portTICK_PERIOD_MS ) ) - { - xEndTime = xTaskGetTickCount(); - xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS; - - ulReturn = xElapsed; - } - else - { + if (ulTimeOut != 0UL) { + if (xQueueReceive(*pxMailBox, &(*ppvBuffer), ulTimeOut / portTICK_PERIOD_MS) == pdTRUE) { + ulReturn = 0; + } else { /* Timed out. */ *ppvBuffer = NULL; ulReturn = SYS_ARCH_TIMEOUT; } - } - else - { - while( pdTRUE != xQueueReceive( *pxMailBox, &( *ppvBuffer ), portMAX_DELAY ) ); - xEndTime = xTaskGetTickCount(); - xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS; - - if( xElapsed == 0UL ) - { - xElapsed = 1UL; - } - - ulReturn = xElapsed; + } else { + while (xQueueReceive(*pxMailBox, &(*ppvBuffer), portMAX_DELAY) != pdTRUE); + ulReturn = 0; } return ulReturn; @@ -263,218 +354,24 @@ unsigned long ulReturn; * u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise, * return ERR_OK. *---------------------------------------------------------------------------*/ -u32_t sys_arch_mbox_tryfetch( sys_mbox_t *pxMailBox, void **ppvBuffer ) +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *pxMailBox, void **ppvBuffer) { -void *pvDummy; -unsigned long ulReturn; -long lResult; -portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + void *pvDummy; + unsigned long ulReturn; - if( ppvBuffer== NULL ) - { + if (ppvBuffer== NULL) { ppvBuffer = &pvDummy; } - if( is_inside_isr() != pdFALSE ) - { - lResult = xQueueReceiveFromISR( *pxMailBox, &( *ppvBuffer ), &xHigherPriorityTaskWoken ); - } - else - { - lResult = xQueueReceive( *pxMailBox, &( *ppvBuffer ), 0UL ); - } - - if( lResult == pdPASS ) - { + if (xQueueReceive(*pxMailBox, &(*ppvBuffer), 0UL) == pdPASS) { ulReturn = ERR_OK; - } - else - { + } else { ulReturn = SYS_MBOX_EMPTY; } return ulReturn; } -/*---------------------------------------------------------------------------* - * Routine: sys_sem_new - *---------------------------------------------------------------------------* - * Description: - * Creates and returns a new semaphore. The "ucCount" argument specifies - * the initial state of the semaphore. - * NOTE: Currently this routine only creates counts of 1 or 0 - * Inputs: - * sys_mbox_t mbox -- Handle of mailbox - * u8_t ucCount -- Initial ucCount of semaphore (1 or 0) - * Outputs: - * sys_sem_t -- Created semaphore or 0 if could not create. - *---------------------------------------------------------------------------*/ -err_t sys_sem_new( sys_sem_t *pxSemaphore, u8_t ucCount ) -{ -err_t xReturn = ERR_MEM; - - vSemaphoreCreateBinary( ( *pxSemaphore ) ); - - if( *pxSemaphore != NULL ) - { - if( ucCount == 0U ) - { - xSemaphoreTake( *pxSemaphore, 1UL ); - } - - xReturn = ERR_OK; - SYS_STATS_INC_USED( sem ); - } - else - { - SYS_STATS_INC( sem.err ); - } - - return xReturn; -} - -/*---------------------------------------------------------------------------* - * Routine: sys_arch_sem_wait - *---------------------------------------------------------------------------* - * Description: - * Blocks the thread while waiting for the semaphore to be - * signaled. If the "timeout" argument is non-zero, the thread should - * only be blocked for the specified time (measured in - * milliseconds). - * - * If the timeout argument is non-zero, the return value is the number of - * milliseconds spent waiting for the semaphore to be signaled. If the - * semaphore wasn't signaled within the specified time, the return value is - * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore - * (i.e., it was already signaled), the function may return zero. - * - * Notice that lwIP implements a function with a similar name, - * sys_sem_wait(), that uses the sys_arch_sem_wait() function. - * Inputs: - * sys_sem_t sem -- Semaphore to wait on - * u32_t timeout -- Number of milliseconds until timeout - * Outputs: - * u32_t -- Time elapsed or SYS_ARCH_TIMEOUT. - *---------------------------------------------------------------------------*/ -u32_t sys_arch_sem_wait( sys_sem_t *pxSemaphore, u32_t ulTimeout ) -{ -TickType_t xStartTime, xEndTime, xElapsed; -unsigned long ulReturn; - - xStartTime = xTaskGetTickCount(); - - if( ulTimeout != 0UL ) - { - if( xSemaphoreTake( *pxSemaphore, ulTimeout / portTICK_PERIOD_MS ) == pdTRUE ) - { - xEndTime = xTaskGetTickCount(); - xElapsed = (xEndTime - xStartTime) * portTICK_PERIOD_MS; - ulReturn = xElapsed; - } - else - { - ulReturn = SYS_ARCH_TIMEOUT; - } - } - else - { - while( xSemaphoreTake( *pxSemaphore, portMAX_DELAY ) != pdTRUE ); - xEndTime = xTaskGetTickCount(); - xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS; - - if( xElapsed == 0UL ) - { - xElapsed = 1UL; - } - - ulReturn = xElapsed; - } - - return ulReturn; -} - -/** Create a new mutex - * @param mutex pointer to the mutex to create - * @return a new mutex */ -err_t sys_mutex_new( sys_mutex_t *pxMutex ) -{ -err_t xReturn = ERR_MEM; - - *pxMutex = xSemaphoreCreateMutex(); - - if( *pxMutex != NULL ) - { - xReturn = ERR_OK; - SYS_STATS_INC_USED( mutex ); - } - else - { - SYS_STATS_INC( mutex.err ); - } - - return xReturn; -} - -/** Lock a mutex - * @param mutex the mutex to lock */ -void sys_mutex_lock( sys_mutex_t *pxMutex ) -{ - while( xSemaphoreTake( *pxMutex, portMAX_DELAY ) != pdPASS ); -} - -/** Unlock a mutex - * @param mutex the mutex to unlock */ -void sys_mutex_unlock(sys_mutex_t *pxMutex ) -{ - xSemaphoreGive( *pxMutex ); -} - - -/** Delete a semaphore - * @param mutex the mutex to delete */ -void sys_mutex_free( sys_mutex_t *pxMutex ) -{ - SYS_STATS_DEC( mutex.used ); - vQueueDelete( *pxMutex ); -} - - -/*---------------------------------------------------------------------------* - * Routine: sys_sem_signal - *---------------------------------------------------------------------------* - * Description: - * Signals (releases) a semaphore - * Inputs: - * sys_sem_t sem -- Semaphore to signal - *---------------------------------------------------------------------------*/ -void sys_sem_signal( sys_sem_t *pxSemaphore ) -{ -portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - - if( is_inside_isr() != pdFALSE ) - { - xSemaphoreGiveFromISR( *pxSemaphore, &xHigherPriorityTaskWoken ); - } - else - { - xSemaphoreGive( *pxSemaphore ); - } -} - -/*---------------------------------------------------------------------------* - * Routine: sys_sem_free - *---------------------------------------------------------------------------* - * Description: - * Deallocates a semaphore - * Inputs: - * sys_sem_t sem -- Semaphore to free - *---------------------------------------------------------------------------*/ -void sys_sem_free( sys_sem_t *pxSemaphore ) -{ - SYS_STATS_DEC(sem.used); - vQueueDelete( *pxSemaphore ); -} - /*---------------------------------------------------------------------------* * Routine: sys_init *---------------------------------------------------------------------------* @@ -508,20 +405,17 @@ u32_t sys_now(void) * Outputs: * sys_thread_t -- Pointer to per-thread timeouts. *---------------------------------------------------------------------------*/ -sys_thread_t sys_thread_new( const char *pcName, void( *pxThread )( void *pvParameters ), void *pvArg, int iStackSize, int iPriority ) +sys_thread_t sys_thread_new(const char *pcName, void(*pxThread)(void *pvParameters), void *pvArg, int iStackSize, int iPriority) { -TaskHandle_t xCreatedTask; -portBASE_TYPE xResult; -sys_thread_t xReturn; + TaskHandle_t xCreatedTask; + portBASE_TYPE xResult; + sys_thread_t xReturn; - xResult = xTaskCreate( pxThread, pcName, iStackSize, pvArg, iPriority, &xCreatedTask ); + xResult = xTaskCreate(pxThread, pcName, iStackSize, pvArg, iPriority, &xCreatedTask); - if( xResult == pdPASS ) - { + if (xResult == pdPASS) { xReturn = xCreatedTask; - } - else - { + } else { xReturn = NULL; } @@ -547,13 +441,14 @@ sys_thread_t xReturn; * Outputs: * sys_prot_t -- Previous protection level (not used here) *---------------------------------------------------------------------------*/ -sys_prot_t sys_arch_protect( void ) +static uint32_t my_nesting = 0; +sys_prot_t sys_arch_protect(void) { - if( is_inside_isr() == pdFALSE ) - { - taskENTER_CRITICAL(); - } - return ( sys_prot_t ) 1; + taskENTER_CRITICAL(); + uint32_t prev = my_nesting; + my_nesting++; + return prev; + //return (sys_prot_t)1; } /*---------------------------------------------------------------------------* @@ -567,26 +462,16 @@ sys_prot_t sys_arch_protect( void ) * Inputs: * sys_prot_t -- Previous protection level (not used here) *---------------------------------------------------------------------------*/ -void sys_arch_unprotect( sys_prot_t xValue ) +void sys_arch_unprotect(sys_prot_t xValue) { - (void) xValue; - if( is_inside_isr() == pdFALSE ) - { - taskEXIT_CRITICAL(); + //(void) xValue; + my_nesting--; + if (xValue != my_nesting) { + printf("lwip nesting %d\n", my_nesting); } + taskEXIT_CRITICAL(); } -/* - * Prints an assertion messages and aborts execution. - */ -void sys_assert( const char *pcMessage ) -{ - (void) pcMessage; - - for (;;) - { - } -} /*-------------------------------------------------------------------------* * End of File: sys_arch.c *-------------------------------------------------------------------------*/ diff --git a/open_esplibs/include/esplibs/libmain.h b/open_esplibs/include/esplibs/libmain.h index 9f4ad1a..593092c 100644 --- a/open_esplibs/include/esplibs/libmain.h +++ b/open_esplibs/include/esplibs/libmain.h @@ -56,6 +56,7 @@ uint32_t sdk_system_relative_time(uint32_t reltime); uint32_t sdk_system_get_checksum(uint8_t *, uint32_t); void sdk_wifi_softap_cacl_mac(uint8_t *, uint8_t *); void sdk_wifi_softap_set_default_ssid(void); +bool sdk_wifi_softap_set_station_info(const uint8_t *hwaddr, ip4_addr_t *); // xtensa_context.o diff --git a/open_esplibs/include/esplibs/libnet80211.h b/open_esplibs/include/esplibs/libnet80211.h index b7a2db6..d2c117b 100644 --- a/open_esplibs/include/esplibs/libnet80211.h +++ b/open_esplibs/include/esplibs/libnet80211.h @@ -32,7 +32,7 @@ struct esf_buf *sdk_ieee80211_getmgtframe(void **arg0, uint32_t arg1, uint32_t a extern uint8_t sdk_TmpSTAAPCloseAP; extern uint8_t sdk_PendFreeBcnEb; void sdk_ieee80211_hostap_attach(struct sdk_g_ic_st *); -void sdk_hostap_handle_timer(struct sdk_netif_conninfo *cnx_node); +void sdk_hostap_handle_timer(struct sdk_cnx_node *cnx_node); bool sdk_wifi_softap_start(); bool sdk_wifi_softap_stop(); @@ -85,10 +85,10 @@ int sdk_chm_check_same_channel(); extern ETSTimer sdk_sta_con_timer; extern void *sdk_g_cnx_probe_rc_list_cb; void sdk_cnx_sta_leave(struct sdk_g_ic_netif_info *netif_info, void *); -void *sdk_cnx_node_search(uint8_t mac[6]); -void sdk_cnx_node_leave(struct sdk_g_ic_netif_info *netif, struct sdk_netif_conninfo *conn); +struct sdk_cnx_node *sdk_cnx_node_search(uint8_t mac[6]); +void sdk_cnx_node_leave(struct sdk_g_ic_netif_info *netif, struct sdk_cnx_node *conn); void sdk_cnx_rc_update_state_metric(void *, int, int); -void sdk_cnx_remove_rc(void *); +void sdk_cnx_node_remove(struct sdk_cnx_node *cnx_node); void sdk_cnx_attach(struct sdk_g_ic_st *); #endif /* _ESPLIBS_LIBNET80211_H */ diff --git a/open_esplibs/include/esplibs/libpp.h b/open_esplibs/include/esplibs/libpp.h index c6185b6..836a689 100644 --- a/open_esplibs/include/esplibs/libpp.h +++ b/open_esplibs/include/esplibs/libpp.h @@ -23,6 +23,7 @@ extern uint8_t sdk_interface_mask; void sdk_ic_set_vif(int, int, uint8_t (*)[6], int, int); void sdk_ic_bss_info_update(int, uint8_t (*hwaddr)[], int, int); void sdk_ic_set_sta(int, int, void *, int, int, int, int, int); +void sdk_ic_remove_key(uint32_t); // lmac.o extern uint32_t sdk_lmacConfMib; diff --git a/open_esplibs/include/esplibs/libwpa.h b/open_esplibs/include/esplibs/libwpa.h index 36a2fc2..2839e56 100644 --- a/open_esplibs/include/esplibs/libwpa.h +++ b/open_esplibs/include/esplibs/libwpa.h @@ -53,6 +53,7 @@ int sdk_os_get_random(uint8_t *dst, uint32_t size); // wpa_auth.o uint32_t *sdk_wpa_init(uint8_t (*hwaddr)[], struct _unknown_wpa1 *, int); +void sdk_wpa_auth_sta_deinit(void *); // wpabuf.o diff --git a/open_esplibs/include/open_esplibs.h b/open_esplibs/include/open_esplibs.h index da59d3c..bcbbcd4 100644 --- a/open_esplibs/include/open_esplibs.h +++ b/open_esplibs/include/open_esplibs.h @@ -6,6 +6,10 @@ // useful for quickly troubleshooting whether a bug is due to the // reimplementation of Espressif libraries, or something else. +// Some source code is mandatory and these are not included as options here. +// For example code referencing lwip structures and flags etc that has changed +// since the initial binary code. + #ifndef OPEN_ESPLIBS #define OPEN_ESPLIBS 1 #endif @@ -32,8 +36,11 @@ #ifndef OPEN_LIBMAIN_XTENSA_CONTEXT #define OPEN_LIBMAIN_XTENSA_CONTEXT (OPEN_LIBMAIN) #endif -#ifndef OPEN_LIBMAIN_USER_INTERFACE -#define OPEN_LIBMAIN_USER_INTERFACE (OPEN_LIBMAIN) +#ifndef OPEN_LIBMAIN_ETS_TIMER +#define OPEN_LIBMAIN_ETS_TIMER (OPEN_LIBMAIN) +#endif +#ifndef OPEN_LIBMAIN_ETS_TIMER +#define OPEN_LIBMAIN_ETS_TIMER (OPEN_LIBMAIN) #endif #ifndef OPEN_LIBNET80211 @@ -42,18 +49,6 @@ #ifndef OPEN_LIBNET80211_ETS #define OPEN_LIBNET80211_ETS (OPEN_LIBNET80211) #endif -#ifndef OPEN_LIBNET80211_HOSTAP -#define OPEN_LIBNET80211_HOSTAP (OPEN_LIBNET80211) -#endif -#ifndef OPEN_LIBNET80211_INPUT -#define OPEN_LIBNET80211_INPUT (OPEN_LIBNET80211) -#endif -#ifndef OPEN_LIBNET80211_STA -#define OPEN_LIBNET80211_STA (OPEN_LIBNET80211) -#endif -#ifndef OPEN_LIBNET80211_WL_CNX -#define OPEN_LIBNET80211_WL_CNX (OPEN_LIBNET80211) -#endif #ifndef OPEN_LIBPHY #define OPEN_LIBPHY (OPEN_ESPLIBS) @@ -115,8 +110,4 @@ #define OPEN_LIBWPA_OS_XTENSA (OPEN_LIBWPA) #endif -#ifndef OPEN_LIBWPA_WPA_MAIN -#define OPEN_LIBWPA_WPA_MAIN (OPEN_LIBWPA) -#endif - #endif /* _OPEN_ESPLIBS_H */ diff --git a/open_esplibs/libmain/ets_timer.c b/open_esplibs/libmain/ets_timer.c new file mode 100644 index 0000000..44b3196 --- /dev/null +++ b/open_esplibs/libmain/ets_timer.c @@ -0,0 +1,340 @@ +/** + * Recreated Espressif libmain ets_timer.o contents. + * + * Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. + * BSD Licensed as described in the file LICENSE + * + * Copyright (c) 2016 sheinz (https://github.com/sheinz) + * + * This module seems to be adapted from NONOS SDK by Espressif to fit into + * RTOS SDK. Function sdk_ets_timer_handler_isr is no longer an ISR handler + * but still holds its name. Espressif just added a task that receives events + * from the real FRC2 timer ISR handler and calls former ISR handler. + * So, timer callbacks are called from the task context rather than an interrupt. + * + * Modifications from the original reverse engineered version: + * - FreeRTOS queue is replaced with Task notifications. + * - Removed unknown queue length monitoring and parameters allocation. + * - Removed unused debug variables + * - xTaskGenericCreate is replaced with xTaskCreate + * - simplified time to ticks conversion (simply multiply by 5) + * + * This timer should be used with caution together with other tasks. As the + * timer callback is executed within timer task context, access to data that + * other tasks accessing should be protected. + */ +#include "open_esplibs.h" + +#if OPEN_LIBMAIN_ETS_TIMER + +#if 0 + +#include "etstimer.h" +#include "espressif/osapi.h" + +void sdk_ets_timer_setfn(ETSTimer *timer, ETSTimerFunc *func, void *parg) { + sdk_os_timer_setfn(timer, func, parg); +} + +void sdk_ets_timer_arm(ETSTimer *timer, uint32_t value, bool repeat_flag) { + sdk_os_timer_arm(timer, value, repeat_flag); +} + +void sdk_ets_timer_arm_ms_us(ETSTimer *timer, uint32_t value, + bool repeat_flag, bool value_in_ms) { + sdk_os_timer_arm(timer, value * 1000 + value_in_ms, repeat_flag); +} + +void sdk_ets_timer_disarm(ETSTimer *timer) { + sdk_os_timer_disarm(timer); +} + +void sdk_ets_timer_init() { +} + +#else + +#include "open_esplibs.h" +#include +#include +#include +#include +#include +#include +#include + +typedef void ets_timer_func_t(void *); + +/** + * This structure is used for both timers: ets_timer.c and timer.c + */ +typedef struct ets_timer_st { + struct ets_timer_st *next; + TimerHandle_t timer_handle; // not used in ets_timer.c + uint32_t fire_ticks; // FRC2 timer value when timer should fire + uint32_t period_ticks; // timer value in FRC2 ticks for rpeating timers + ets_timer_func_t *callback; + bool repeat; // not used in ets_timer.c + void *timer_arg; +} ets_timer_t; + +/** + * Special values of ets_timer_t::next field + */ +#define ETS_TIMER_NOT_ARMED (ets_timer_t*)(0xffffffff) +#define ETS_TIMER_LIST_END (ets_timer_t*)(0) + +/** + * Linked list of timers + */ +static ets_timer_t* timer_list = 0; + +static TaskHandle_t task_handle = NULL; + +void sdk_ets_timer_setfn(ets_timer_t *timer, ets_timer_func_t *func, void *parg) +{ + timer->callback = func; + timer->timer_arg = parg; + timer->fire_ticks = 0; + timer->period_ticks = 0; + timer->next = ETS_TIMER_NOT_ARMED; +} + +static inline void set_alarm_value(uint32_t value) +{ + TIMER_FRC2.ALARM = value; +} + +/** + * Set timer alarm and make sure the alarm is set in the future + * and will not be missed by the timer. + */ +static void set_alarm(uint32_t ticks) +{ + uint32_t curr_time = TIMER_FRC2.COUNT; + int32_t delta = (int32_t)ticks - curr_time; + if ((delta - 40) < 1) { + if (delta < 1) { + set_alarm_value(curr_time + 40); + } else { + set_alarm_value(ticks + 44); + } + } else { + set_alarm_value(ticks); + } +} + +/** + * + * Pending timer list example: + * + * | Timer: | T0 | T1 | T2 | T3 | + * |-------------|----|----|----|----| + * | fire_ticks: | 10 | 20 | 30 | 40 | + * | next: | T1 | T2 | T3 | 0 | + * + * + * For example we need to add a timer that should fire at 25 ticks: + * + * | Timer: | T0 | T1 | new | T2 | T3 | + * |-------------|----|-----|-----|----|----| + * | fire_ticks: | 10 | 20 | 25 | 30 | 40 | + * | next: | T1 | new | T2 | T3 | 0 | + * + * We squeeze the timer into the list so the list will always remain sorted + * + * Note: if add the same timer twice the system halts +*/ +static void add_pending_timer(uint32_t ticks, ets_timer_t *timer) +{ + ets_timer_t *prev = 0; + ets_timer_t *curr = timer_list; + while (curr) { + if (((int32_t)ticks - (int32_t)curr->fire_ticks) < 1) { + // found a timer that should fire later + // so our timer should fire earlier + break; + } + prev = curr; + curr = curr->next; + } + + timer->next = curr; + timer->fire_ticks = ticks; + + if (prev != 0) { + prev->next = timer; + } else { + // Our timer is the first in the line to fire + timer_list = timer; + set_alarm(ticks); + } + + // This situation might happen if adding the same timer twice + if (timer == timer->next) { + // This seems like an error: %s is used for line number + // In the recent SDK Espressif fixed the format to "%s %u\n" + printf("%s %s \n", "ets_timer.c", (char*)209); + while (1); + } +} + +/** + * In the Espressif SDK 0.9.9 if try to arm already armed timer the system halts + * with error message. In the later SDK version Espressif changed the behavior. + * If the timer was previously armed it is disarmed and then armed without errors. + * This version recreates behavior of SDK 0.9.9 + */ +void sdk_ets_timer_arm_ms_us(ets_timer_t *timer, uint32_t value, + bool repeat_flag, bool value_in_ms) +{ + uint32_t ticks = 0; + + if (timer->next != ETS_TIMER_NOT_ARMED) { + // The error message doesn't tell what is wrong + printf("arm new %x %x\n", (uint32_t)timer, (uint32_t)timer->next); + while(1); // halt + } + + if (value_in_ms) { + ticks = value * 5000; + } else { + ticks = value * 5; + } + + if (repeat_flag) { + timer->period_ticks = ticks; + } + vPortEnterCritical(); + add_pending_timer(TIMER_FRC2.COUNT + ticks, timer); + vPortExitCritical(); +} + +void sdk_ets_timer_arm(ets_timer_t *timer, uint32_t milliseconds, + bool repeat_flag) +{ + sdk_ets_timer_arm_ms_us(timer, milliseconds, repeat_flag, + /*value in ms=*/true); +} + +void sdk_ets_timer_arm_us(ets_timer_t *timer, uint32_t useconds, + bool repeat_flag) +{ + sdk_ets_timer_arm_ms_us(timer, useconds, repeat_flag, + /*value in ms=*/false); +} + +/** + * Function removes a timer from the pending timers list. + */ +void sdk_ets_timer_disarm(ets_timer_t *timer) +{ + vPortEnterCritical(); + ets_timer_t *curr = timer_list; + ets_timer_t *prev = 0; + while (curr) { + if (curr == timer) { + if (prev) { + prev->next = curr->next; + } else { + timer_list = curr->next; + } + break; + } + prev = curr; + curr = curr->next; + } + vPortExitCritical(); + timer->next = ETS_TIMER_NOT_ARMED; + timer->period_ticks = 0; +} + +/** + * Check the list of pending timers for expired ones and process them. + */ +static inline void process_pending_timers() +{ + vPortEnterCritical(); + int32_t ticks = TIMER_FRC2.COUNT; + while (timer_list) { + if (((int32_t)timer_list->fire_ticks - ticks) < 1) { + ets_timer_t *timer = timer_list; + timer_list = timer->next; + timer->next = ETS_TIMER_NOT_ARMED; + + vPortExitCritical(); + timer->callback(timer->timer_arg); + vPortEnterCritical(); + + if (timer->next == ETS_TIMER_NOT_ARMED) { + if (timer->period_ticks) { + timer->fire_ticks = timer->fire_ticks + timer->period_ticks; + add_pending_timer(timer->fire_ticks, timer); + } + } + ticks = TIMER_FRC2.COUNT; + } else { + if (timer_list) { + set_alarm(timer_list->fire_ticks); + } + break; + } + } + vPortExitCritical(); +} + +/** + * .Lfunc002 + */ +static void IRAM frc2_isr(void *arg) +{ + BaseType_t task_woken = 0; + + BaseType_t result = xTaskNotifyFromISR(task_handle, 0, eNoAction, &task_woken); + if (result != pdTRUE) { + printf("TIMQ_FL:%d!!", (uint32_t)result); + } + + portEND_SWITCHING_ISR(task_woken); +} + +/** + * .Lfunc007 + * + * Timer task + */ +static void timer_task(void* param) +{ + while (true) { + if (xTaskNotifyWait(0, 0, NULL, portMAX_DELAY) == pdTRUE) { + process_pending_timers(); + } + } +} + +void sdk_ets_timer_init() +{ + timer_list = 0; + + _xt_isr_attach(INUM_TIMER_FRC2, frc2_isr, NULL); + + /* Original code calls xTaskGenericCreate: + * xTaskGenericCreate(task_handle, "rtc_timer_task", 200, 0, 12, &handle, + * NULL, NULL); + */ + xTaskCreate(timer_task, "rtc_timer_task", 200, 0, 12, &task_handle); + printf("frc2_timer_task_hdl:%p, prio:%d, stack:%d\n", task_handle, 12, 200); + + TIMER_FRC2.ALARM = 0; + TIMER_FRC2.CTRL = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_16) + | TIMER_CTRL_RUN; + TIMER_FRC2.LOAD = 0; + + DPORT.INT_ENABLE |= DPORT_INT_ENABLE_TIMER1; + + _xt_isr_unmask(BIT(INUM_TIMER_FRC2)); +} + +#endif + +#endif /* OPEN_LIBMAIN_ETS_TIMER */ diff --git a/open_esplibs/libmain/os_cpu_a.c b/open_esplibs/libmain/os_cpu_a.c index 7fd3719..fdabb56 100644 --- a/open_esplibs/libmain/os_cpu_a.c +++ b/open_esplibs/libmain/os_cpu_a.c @@ -69,7 +69,7 @@ void IRAM sdk__xt_int_exit(void) { "); } -void IRAM sdk__xt_timer_int(void) { +void IRAM sdk__xt_timer_int(void *arg) { uint32_t trigger_ccount; uint32_t current_ccount; uint32_t ccount_interval = portTICK_PERIOD_MS * sdk_os_get_cpu_frequency() * 1000; diff --git a/open_esplibs/libmain/user_interface.c b/open_esplibs/libmain/user_interface.c index eed34a1..a21530d 100644 --- a/open_esplibs/libmain/user_interface.c +++ b/open_esplibs/libmain/user_interface.c @@ -3,9 +3,6 @@ Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. BSD Licensed as described in the file LICENSE */ -#include "open_esplibs.h" -#if OPEN_LIBMAIN_USER_INTERFACE -// The contents of this file are only built if OPEN_LIBMAIN_USER_INTERFACE is set to true #include "FreeRTOS.h" #include "task.h" @@ -147,8 +144,8 @@ bool IRAM sdk_system_rtc_mem_read(uint32_t src_addr, void *des_addr, uint16_t sa return true; } -void sdk_system_pp_recycle_rx_pkt(void *eb) { - sdk_ppRecycleRxPkt(eb); +void sdk_system_pp_recycle_rx_pkt(struct esf_buf *esf_buf) { + sdk_ppRecycleRxPkt(esf_buf); } uint16_t sdk_system_adc_read(void) { @@ -471,8 +468,7 @@ uint32_t sdk_system_relative_time(uint32_t reltime) { return WDEV.SYS_TIME - reltime; } -// Change arg types to ip4_addr for lwip v2. -void sdk_system_station_got_ip_set(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw) { +void sdk_system_station_got_ip_set(struct ip4_addr *ip, struct ip4_addr *mask, struct ip4_addr *gw) { uint8_t *ip_bytes = (uint8_t *)&ip->addr; uint8_t *mask_bytes = (uint8_t *)&mask->addr; uint8_t *gw_bytes = (uint8_t *)&gw->addr; @@ -588,9 +584,9 @@ bool sdk_wifi_get_ip_info(uint8_t if_index, struct ip_info *info) { if (!info) return false; struct netif *netif = _get_netif(if_index); if (netif) { - info->ip = netif->ip_addr; - info->netmask = netif->netmask; - info->gw = netif->gw; + ip4_addr_set(&info->ip, ip_2_ip4(&netif->ip_addr)); + ip4_addr_set(&info->netmask, ip_2_ip4(&netif->netmask)); + ip4_addr_set(&info->gw, ip_2_ip4(&netif->gw)); return true; } @@ -719,5 +715,3 @@ bool sdk_wifi_set_sleep_type(enum sdk_sleep_type type) sdk_pm_set_sleep_type_from_upper(type); return true; } - -#endif /* OPEN_LIBMAIN_USER_INTERFACE */ diff --git a/open_esplibs/libnet80211/ieee80211_hostap.c b/open_esplibs/libnet80211/ieee80211_hostap.c index fbe7f49..74f9675 100644 --- a/open_esplibs/libnet80211/ieee80211_hostap.c +++ b/open_esplibs/libnet80211/ieee80211_hostap.c @@ -3,8 +3,306 @@ Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. BSD Licensed as described in the file LICENSE */ -#include "open_esplibs.h" -#if OPEN_LIBNET80211_HOSTAP -// The contents of this file are only built if OPEN_LIBNET80211_HOSTAP is set to true -#endif /* OPEN_LIBNET80211_HOSTAP */ +#include +#include "tcpip.h" +#include "espressif/esp_wifi.h" +#include "espressif/esp_misc.h" +#include "etstimer.h" +#include "esplibs/libmain.h" +#include "esplibs/libnet80211.h" +#include "esplibs/libpp.h" +#include "esplibs/libwpa.h" + +static uint8_t hostap_flags = 0; +static ETSTimer hostap_timer; +static struct esf_buf *hostap_timer_parg = NULL; + +void IRAM *zalloc(size_t nbytes); + +static void IRAM hostap_timer_func(struct esf_buf *esf_buf) { + struct sdk_cnx_node *cnx_node = sdk_g_ic.v.softap_netif_info->cnx_nodes[0]; + int32_t mode = sdk_wifi_get_phy_mode(); + uint8_t *frame = esf_buf->frame; + *(uint16_t *)(frame + 22) = (cnx_node->_unknown9c - 1) << 4; + + cnx_node->_unknown9c += 1; + + if (sdk_g_ic.s.wifi_led_enable) { + uint32_t gpio = sdk_g_ic.s.wifi_led_gpio; + uint32_t state = sdk_g_ic.s.wifi_led_state; + sdk_gpio_output_set(state << gpio, (((state & 1) == 0) ? 1 : 0) << gpio, + 1 << gpio, 0); + sdk_g_ic.s.wifi_led_state = (state & 1) ? 0 : 1; + } + + uint8_t *frame2 = frame + sdk_g_ic.s._unknown288 + (mode == 1 ? 23 : 27) ; + memcpy(frame2 + 29, &sdk_g_ic.v._unknown1d2, 1); + + uint32_t v1 = frame2[26]; + if (v1 == 0) { + v1 = frame2[27]; + } + frame2[26] = v1 - 1; + + uint32_t v2 = sdk_ieee80211_chan2ieee(sdk_g_ic.v._unknown14c); + frame2[23] = v2; + sdk_g_ic.s._unknown30d = v2; + + int32_t v3 = *((volatile int32_t *)0x3ff20c00); // mactime + *(uint32_t *)(esf_buf->extra + 16) = v3; + *(uint32_t *)(frame + 24) = v3; + *(uint32_t *)(frame + 28) = 0; + + if (sdk_chm_check_same_channel()) { + hostap_flags |= 1; + sdk_ppTxPkt(esf_buf); + return; + } + sdk_ets_timer_disarm(&hostap_timer); + sdk_ets_timer_arm(&hostap_timer, sdk_wDev_Get_Next_TBTT(), 0); +} + +static void IRAM hostap_tx_callback() { + uint32_t flags = hostap_flags & 0xfe; + + if (sdk_TmpSTAAPCloseAP == 0) { + hostap_flags = flags; + sdk_ets_timer_disarm(&hostap_timer); + sdk_ets_timer_arm(&hostap_timer, sdk_wDev_Get_Next_TBTT(), 0); + return; + } + + sdk_PendFreeBcnEb = 1; + + if (flags & 2) { + hostap_flags = flags & 0xfd; + sdk_wifi_softap_start(); + return; + } + + hostap_flags = flags; +} + +static void hostap_attach_misc() { + struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.softap_netif_info; + + struct _unknown_softap1 *ptr1 = zalloc(28); // 0x1c + netif_info->_unknownb4 = ptr1; + + struct _unknown_softap2 *ptr2 = zalloc(204); // 0xcc + ptr1->_unknown04 = ptr2; + + struct _unknown_wpa1 *ptr3 = zalloc(76); // 0x4c + + uint32_t v1 = sdk_g_ic.s._unknown30e; + if (v1 == 2) { + ptr3->_unknown00 = 1; + } else if (v1 == 3) { + ptr3->_unknown00 = 2; + } else if (v1 == 4) { + ptr3->_unknown00 = 3; + } + + ptr3->_unknown28 = 2; + ptr3->_unknown04 = 2; + ptr3->_unknown0c = 2; + ptr3->_unknown08 = 10; + ptr3->_unknown20 = 10; + + int s1 = (sdk_g_ic.s._unknown28a << 16) | sdk_g_ic.s._unknown288; + memcpy(&ptr2->_unknown10, &sdk_g_ic.s._unknown28c, s1); + ptr2->_unknown30 = s1; + + uint8_t *ptr4 = zalloc(64); // 0x40 + ptr2->_unknown3c = ptr4; + + char *str1 = sdk_g_ic.s._unknown2ac; + memcpy(ptr4, str1, strlen(str1)); + + struct sdk_cnx_node *cnx_node = netif_info->cnx_nodes[0]; + + ptr2->_unknownb4 = 300; + + netif_info->_unknown4c = 3; + netif_info->_unknown48 |= 16; + + cnx_node->_unknown08 |= 1; + + sdk_hostapd_setup_wpa_psk(ptr2); + + struct netif *netif = netif_info->netif; + + ptr1->_unknown18 = sdk_wpa_init(&netif->hwaddr, ptr3, 0); + + free(ptr3); +} + +static void softap_stop_free() { + struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.softap_netif_info; + netif_info->_unknown4c = 0; + netif_info->_unknown48 &= 0xffffffef; + netif_info->cnx_nodes[0]->_unknown08 = 0; + + struct _unknown_softap1 *unkb4 = netif_info->_unknownb4; + if (!unkb4) return; + + uint32_t *unk18 = unkb4->_unknown18; + if (unk18) { + uint32_t *ptr1 = ((uint32_t **)unk18)[20]; + if (ptr1) + free(ptr1); + + uint32_t *ptr2 = *(uint32_t **)unk18; + if (ptr2) + free(ptr2); + + free(unk18); + } + + struct _unknown_softap2 *unk04 = unkb4->_unknown04; + if (unk04) { + uint32_t *unk38 = unk04->_unknown38; + if (unk38) + free(unk38); + + uint8_t *unk3c = unk04->_unknown3c; + if (unk3c) + free(unk3c); + + free(unk04); + } + + free(unkb4); + netif_info->_unknownb4 = NULL; +} + +void sdk_ieee80211_hostap_attach(struct sdk_g_ic_st *ic) { + uint32_t scratch[12]; // ?? + struct sdk_g_ic_netif_info *netif_info = ic->v.softap_netif_info; + + uint32_t v1 = ic->s._unknown30e; + if (v1 >= 2 && v1 < 5) + hostap_attach_misc(); + + struct netif *netif = netif_info->netif; + sdk_ic_bss_info_update(1, &netif->hwaddr, 2, 100); + + ic->v._unknown1d0 = 0; + netif_info->_unknown3c = 5; + + sdk_ppRegisterTxCallback(hostap_tx_callback, 4); + + hostap_timer_parg = sdk_ieee80211_beacon_alloc(netif_info, scratch); + sdk_ets_timer_disarm(&hostap_timer); + sdk_ets_timer_setfn(&hostap_timer, (ETSTimerFunc *)hostap_timer_func, hostap_timer_parg); + sdk_wDev_Reset_TBTT(); + sdk_ets_timer_arm(&hostap_timer, sdk_wDev_Get_Next_TBTT(), 0); +} + +bool sdk_wifi_softap_start() { + struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.softap_netif_info; + if (!netif_info) return 0; + if (netif_info->started) return 1; + + uint8_t flags = hostap_flags; + if (flags & 1) { + hostap_flags = flags | 2; + return 1; + } + + uint8_t (*mac_addr)[6] = &sdk_info.softap_mac_addr; + if (!netif_info->netif) { + struct netif *netif = (struct netif *)malloc(sizeof(struct netif)); + netif_info->netif = netif; + memcpy(&netif->hwaddr, mac_addr, 6); + netif_add(netif, &sdk_info.softap_ipaddr, &sdk_info.softap_netmask, + &sdk_info.softap_gw, netif_info, ethernetif_init, tcpip_input); + } + + sdk_ic_set_vif(1, 1, mac_addr, 1, 0); + + netif_set_up(netif_info->netif); + + if (sdk_wifi_get_opmode() != 3 || + !sdk_g_ic.v.station_netif_info || + sdk_g_ic.v.station_netif_info->_unknown3c < 2) { + + uint32_t i1 = (sdk_g_ic.s._unknown30d - 1) & 0xff; + + int nmi_on = sdk_NMIIrqIsOn; + if (!nmi_on) { + vPortEnterCritical(); + + do { + DPORT.DPORT0 = DPORT.DPORT0 & 0xffffffe0; + } while (DPORT.DPORT0 & 1); + } + + // current channel? + uint32_t *chan = &sdk_g_ic.v._unknown84[i1 * 3]; + sdk_g_ic.v._unknown14c = chan; + + if (!nmi_on) { + DPORT.DPORT0 = (DPORT.DPORT0 & 0xffffffe0) | 1; + vPortExitCritical(); + } + + sdk_chm_set_current_channel(chan); + } + + sdk_ieee80211_hostap_attach(&sdk_g_ic); + sdk_TmpSTAAPCloseAP = 0; + netif_info->started = 1; + return 1; +} + +bool sdk_wifi_softap_stop() { + struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.softap_netif_info; + + if (!netif_info) + return 0; + + if (!netif_info->started) + return 1; + + uint32_t end = sdk_g_ic.s._unknown310 + 2; + uint32_t count = 1; + + // Note this defensive test seems dead code, the value is loaded + // as a uint8_t value so adding 2 ensures this test always passes. + if (end >= 2) { + do { + struct sdk_cnx_node *cnx_node = netif_info->cnx_nodes[count]; + if (cnx_node) { + struct sdk_cnx_node *cnx_node2 = netif_info->_unknown88; + netif_info->_unknown88 = cnx_node; + + sdk_ieee80211_send_mgmt(netif_info, 160, 4); + sdk_ieee80211_send_mgmt(netif_info, 192, 2); + + netif_info->_unknown88 = cnx_node2; + + sdk_cnx_node_leave(netif_info, netif_info->cnx_nodes[count]); + + // Number of entries might have changed, perhaps + // should have if one was removed above? + end = sdk_g_ic.s._unknown310 + 2; + } + count++; + } while (count < end); + } + + netif_set_down(netif_info->netif); + sdk_TmpSTAAPCloseAP = 1; + sdk_ets_timer_disarm(&hostap_timer); + sdk_ic_bss_info_update(1, &sdk_info.softap_mac_addr, 2, 0); + sdk_ic_set_vif(1, 0, NULL, 1, 0); + softap_stop_free(); + + if ((hostap_flags & 1) == 0) + sdk_esf_buf_recycle(hostap_timer_parg, 4); + + netif_info->started = 0; + return 1; +} diff --git a/open_esplibs/libnet80211/ieee80211_input.c b/open_esplibs/libnet80211/ieee80211_input.c index be07a51..583dba9 100644 --- a/open_esplibs/libnet80211/ieee80211_input.c +++ b/open_esplibs/libnet80211/ieee80211_input.c @@ -3,9 +3,6 @@ Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. BSD Licensed as described in the file LICENSE */ -#include "open_esplibs.h" -#if OPEN_LIBNET80211_INPUT -// The contents of this file are only built if OPEN_LIBNET80211_INPUT is set to true #include "esplibs/libpp.h" @@ -14,10 +11,9 @@ void IRAM sdk_ieee80211_deliver_data(struct sdk_g_ic_netif_info *netif_info, str if (netif->flags & NETIF_FLAG_LINK_UP) { uint16_t length = esf_buf->length; - struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, length, PBUF_REF); - pbuf->payload = esf_buf->pbuf2->payload; + struct pbuf *pbuf = pbuf_alloc_reference(esf_buf->pbuf2->payload, length, PBUF_ALLOC_FLAG_RX | PBUF_TYPE_ALLOC_SRC_MASK_ESP_RX); esf_buf->pbuf1 = pbuf; - pbuf->eb = (void *)esf_buf; + pbuf->esf_buf = (void *)esf_buf; ethernetif_input(netif, pbuf); return; } @@ -27,5 +23,3 @@ void IRAM sdk_ieee80211_deliver_data(struct sdk_g_ic_netif_info *netif_info, str return; } - -#endif /* OPEN_LIBNET80211_INPUT */ diff --git a/open_esplibs/libnet80211/ieee80211_sta.c b/open_esplibs/libnet80211/ieee80211_sta.c index 5362dc3..3e7f695 100644 --- a/open_esplibs/libnet80211/ieee80211_sta.c +++ b/open_esplibs/libnet80211/ieee80211_sta.c @@ -3,9 +3,6 @@ Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. BSD Licensed as described in the file LICENSE */ -#include "open_esplibs.h" -#if OPEN_LIBNET80211_STA -// The contents of this file are only built if OPEN_LIBNET80211_STA is set to true #include #include "esplibs/libmain.h" @@ -72,5 +69,3 @@ bool sdk_wifi_station_stop() { return 1; } - -#endif /* OPEN_LIBNET80211_STA */ diff --git a/open_esplibs/libnet80211/wl_cnx.c b/open_esplibs/libnet80211/wl_cnx.c index 3b7d709..3b49c5d 100644 --- a/open_esplibs/libnet80211/wl_cnx.c +++ b/open_esplibs/libnet80211/wl_cnx.c @@ -3,17 +3,103 @@ Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. BSD Licensed as described in the file LICENSE */ -#include "open_esplibs.h" -#if OPEN_LIBNET80211_WL_CNX -// The contents of this file are only built if OPEN_LIBNET80211_WL_CNX is set to true #include "espressif/esp_misc.h" #include "esplibs/libnet80211.h" +#include "esplibs/libpp.h" +#include "esplibs/libwpa.h" #include #include "lwip/dhcp.h" -ETSTimer sdk_sta_con_timer; -void *sdk_g_cnx_probe_rc_list_cb; +/* Need to use the sdk versions of these for now as there are reference to them + * relative to other data structres. */ +extern ETSTimer sdk_sta_con_timer; +extern void *sdk_g_cnx_probe_rc_list_cb; + +/* + * Called from the ESP sdk_cnx_sta_leave function. Split out via a hack to the + * binary library to allow modification to track changes to lwip, for example + * changes to the offset of the netif->flags removal of the NETIF_FLAG_DHCP flag + * lwip v2 etc. + */ +void dhcp_if_down(struct netif *netif) +{ + dhcp_release_and_stop(netif); + netif_set_down(netif); +} + +struct sdk_cnx_node *sdk_cnx_rc_search(uint8_t *hwaddr) { + size_t len = *(uint8_t *)(sdk_g_ic.v._unknown0 + 0x689); + struct sdk_cnx_node **table = (struct sdk_cnx_node **)(sdk_g_ic.v._unknown0 + 0x670); + size_t i; + + for (i = 0; i < len; i++) { + struct sdk_cnx_node *cnx_node = table[i]; + if (cnx_node && memcmp(cnx_node->mac_addr, hwaddr, 6) == 0) { + return cnx_node; + } + } + + return NULL; +} + +int sdk_cnx_add_rc(struct sdk_cnx_node *cnx_node) { + size_t len = *(uint8_t *)(sdk_g_ic.v._unknown0 + 0x689); + struct sdk_cnx_node **table = (struct sdk_cnx_node **)(sdk_g_ic.v._unknown0 + 0x670); + + if (len >= 6) { + return -1; + } + + if (len < 2) { + table[len] = cnx_node; + } else { + struct wl_channel *channel = cnx_node->channel; + size_t found; + for (found = 0; found < len; found++) { + if (table[found]->channel == channel) { + break; + } + } + + if (found >= len) { + /* Add to the end. */ + table[len] = cnx_node; + } else { + /* Make room. */ + size_t next = found + 1; + size_t i; + for (i = len; i > next; i--) { + table[i] = table[i - 1];; + } + table[next] = cnx_node; + } + } + + *(uint8_t *)(sdk_g_ic.v._unknown0 + 0x689) += 1; + return 0; +} + +void sdk_cnx_remove_rc(struct sdk_cnx_node *cnx_node) { + size_t len = *(uint8_t *)(sdk_g_ic.v._unknown0 + 0x689); + struct sdk_cnx_node **table = (struct sdk_cnx_node **)(sdk_g_ic.v._unknown0 + 0x670); + size_t i; + + for (i = 0; i < len; i++) { + if (table[i] == cnx_node) { + bzero(cnx_node, 0x110); + table[i] = NULL; + len -= 1; + *(uint8_t *)(sdk_g_ic.v._unknown0 + 0x689) = len; + break; + } + } + + /* Fill the hole */ + for (; i < len; i++) { + table[i] = table[i + 1]; + } +} #if 0 @@ -24,7 +110,6 @@ static uint8_t Ldata004; static uint32_t Ldata006; static void *Ldate007; -// Use of the netif->flags and the NETIF_FLAG_DHCP flag removed in lwip v2. void sdk_cnx_sta_leave(struct sdk_g_ic_netif_info *netif_info, void *arg1) { struct netif *netif = netif_info->netif; @@ -32,13 +117,9 @@ void sdk_cnx_sta_leave(struct sdk_g_ic_netif_info *netif_info, void *arg1) { uint16_t v1 = *(uint16_t *)(arg1 + 0x1a) & 0xfff; sdk_ic_set_sta(0, 0, arg1, 0, v1, phy_type, 0, 0); - netif_set_down(netif); - - // The NETIF_FLAG_DHCP flags is removed in lwip v2? - if (netif->flags & 0x8) { - dhcp_release(netif); - dhcp_stop(netif); - } + // Note the SDK binary was modified here as it made use of the + // netif flags which changed in lwip v2. + dhcp_if_down(netif); uint32_t v2 = *(uint8_t *)(arg1 + 0xe8); free(sdk_g_ic.v._unknown190[v2]); @@ -77,7 +158,30 @@ void sdk_cnx_sta_leave(struct sdk_g_ic_netif_info *netif_info, void *arg1) { } #endif -void IRAM *sdk_cnx_node_search(uint8_t mac[6]) +void sdk_cnx_node_remove(struct sdk_cnx_node *cnx_node) { + const uint32_t num = sdk_g_ic.s._unknown310 + 2; + if ((int32_t)num < (int32_t)2) { + return; + } + + struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.softap_netif_info; + uint32_t i = 1; + do { + if (netif_info->cnx_nodes[i] == cnx_node) { + uint32_t v2 = cnx_node->_unknowne8; + sdk_ic_remove_key(v2 + 2); + sdk_wpa_auth_sta_deinit(cnx_node->_unknowne4); + free(sdk_g_ic.v._unknown190[v2]); + sdk_g_ic.v._unknown190[v2] = NULL; + free(cnx_node); + netif_info->cnx_nodes[i] = NULL; + return; + } + i += 1; + } while (i < num); +} + +struct sdk_cnx_node *sdk_cnx_node_search(uint8_t mac[6]) { int end = sdk_g_ic.s._unknown310 + 2; @@ -86,15 +190,15 @@ void IRAM *sdk_cnx_node_search(uint8_t mac[6]) if (end < 1) return NULL; - struct sdk_netif_conninfo **conninfo = sdk_g_ic.v.softap_netif_info->conninfo; + struct sdk_cnx_node **cnx_nodes = sdk_g_ic.v.softap_netif_info->cnx_nodes; int i = 0; do { - struct sdk_netif_conninfo *info = conninfo[i]; + struct sdk_cnx_node *cnx_node = cnx_nodes[i]; - if (info) { - if (memcmp(mac, info->mac_addr, 6) == 0) { - return info; + if (cnx_node) { + if (memcmp(mac, cnx_node->mac_addr, 6) == 0) { + return cnx_node; } } i++; @@ -102,5 +206,3 @@ void IRAM *sdk_cnx_node_search(uint8_t mac[6]) return NULL; } - -#endif /* OPEN_LIBNET80211_WL_CNX */ diff --git a/open_esplibs/libpp/wdev.c b/open_esplibs/libpp/wdev.c index 1564a59..902b3dc 100644 --- a/open_esplibs/libpp/wdev.c +++ b/open_esplibs/libpp/wdev.c @@ -5,7 +5,13 @@ */ #include "open_esplibs.h" #if OPEN_LIBPP_WDEV -// The contents of this file are only built if OPEN_LIBPHY_PHY_CHIP_SLEEP is set to true +// The contents of this file are only built if OPEN_LIBPP_WDEV is set to true +// Note the SDK allocated 8000 bytes for TX buffers that appears to be +// unused. Rather TX buffers appear to be allocated by upper layers. The +// location of this areas is at wDevCtrl + 0x2190. The SDK has been modified +// to allocate only one word (4 bytes) per buffer on initialization and even +// these seem unused but to be sure avoid the first 20 bytes. So there are +// 7980 bytes free starting at wDevCtrl + 0x21a4. #endif /* OPEN_LIBPP_WDEV */ diff --git a/open_esplibs/libwpa/wpa_main.c b/open_esplibs/libwpa/wpa_main.c index 1c70516..e13e3b6 100644 --- a/open_esplibs/libwpa/wpa_main.c +++ b/open_esplibs/libwpa/wpa_main.c @@ -3,13 +3,13 @@ Copyright (C) 2015 Espressif Systems. Derived from MIT Licensed SDK libraries. BSD Licensed as described in the file LICENSE */ -#include "open_esplibs.h" -#if OPEN_LIBWPA_WPA_MAIN -// The contents of this file are only built if OPEN_LIBWPA_WPA_MAIN is set to true +#include +#include #include "espressif/user_interface.h" #include "etstimer.h" #include "espressif/osapi.h" +#include "espressif/esp_sta.h" #include "esplibs/libnet80211.h" #include "esplibs/libmain.h" #include "esplibs/libwpa.h" @@ -44,8 +44,8 @@ void sdk_wpa_config_bss(struct sdk_g_ic_st *g_ic, uint8_t (* hwaddr2)[6]) { struct sdk_g_ic_netif_info *netif_info = g_ic->v.station_netif_info; struct netif *netif = netif_info->netif; sdk_wpa_set_bss(netif->hwaddr, hwaddr2, g_ic->s._unknown20a, g_ic->s._unknown20c, - g_ic->s.sta_password, g_ic->s._unknown1e4.sta_ssid, - (g_ic->s._unknown1e4._unknown1e6 << 16) | g_ic->s._unknown1e4._unknown1e4); + g_ic->s.sta_password, g_ic->s.sta_ssid.ssid, + g_ic->s.sta_ssid.ssid_length); } void sdk_wpa_config_assoc_ie(int arg0, int16_t *arg1, int32_t arg2) { @@ -57,14 +57,14 @@ void sdk_wpa_config_assoc_ie(int arg0, int16_t *arg1, int32_t arg2) { *arg1 = arg2; } -void sdk_dhcp_bind_check() { +void sdk_dhcp_bind_check(void *parg) { struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.station_netif_info; uint8_t connect_status = netif_info->connect_status; uint8_t unknown20a = sdk_g_ic.s._unknown20a; - if (connect_status != 5) { + if (connect_status != STATION_GOT_IP) { if (unknown20a == 7 || unknown20a == 8) { - netif_info->connect_status = 2; + netif_info->connect_status = STATION_CONNECTING; } } } @@ -72,13 +72,13 @@ void sdk_dhcp_bind_check() { void sdk_eagle_auth_done() { struct sdk_g_ic_netif_info *netif_info = sdk_g_ic.v.station_netif_info; struct netif *netif = netif_info->netif; - struct sdk_netif_conninfo *conninfo = netif_info->_unknown88; + struct sdk_cnx_node *cnx_node = netif_info->_unknown88; - if (conninfo->_unknown08 & 1) + if (cnx_node->_unknown08 & 1) return; - uint32_t channel = conninfo->_unknown78->channel; - char *ssid = (char *)sdk_g_ic.s._unknown1e4.sta_ssid; + uint32_t channel = cnx_node->channel->num; + char *ssid = (char *)sdk_g_ic.s.sta_ssid.ssid; printf("\nconnected with %s, channel %d\n", ssid, channel); RTCMEM_SYSTEM[61] = 0x00010000 | channel; @@ -89,24 +89,29 @@ void sdk_eagle_auth_done() { sdk_os_timer_arm(timer, 15000, 0); netif_info->statusb9 = 0; - conninfo->_unknown18 = 0; - conninfo->_unknown08 |= 1; + cnx_node->_unknown18 = 0; + cnx_node->_unknown08 |= 1; - // TODO lwip v2 removed the NETIF_FLAG_DHCP flag. - if (netif->flags & 0x08) // NETIF_FLAG_DHCP + if (dhcp_supplied_address(netif)) return; - // lwip v2: if (ip4_addr_isany_val(netif->ip_addr)) { - if (netif->ip_addr.addr == 0) { - if (sdk_dhcpc_flag != DHCP_STOPPED) { - printf("dhcp client start...\n"); - dhcp_start(netif); - } + if (sdk_dhcpc_flag != DHCP_STOPPED) { + printf("dhcp client start...\n"); + netif_set_up(netif); + dhcp_start(netif); return; } - system_station_got_ip_set(&netif->ip_addr, &netif->netmask, &netif->gw); + if (ip4_addr_isany_val(sdk_info.sta_ipaddr)) { + printf("expected a static ip address?\n"); + return; + } + + netif_set_addr(netif, &sdk_info.sta_ipaddr, &sdk_info.sta_netmask, &sdk_info.sta_gw); netif_set_up(netif); + sdk_system_station_got_ip_set(ip_2_ip4(&netif->ip_addr), + ip_2_ip4(&netif->netmask), + ip_2_ip4(&netif->gw)); } void sdk_wpa_neg_complete() { @@ -120,5 +125,3 @@ void sdk_wpa_attach(struct sdk_g_ic_st *g_ic) { wpa_callback2, sdk_wpa_neg_complete); sdk_ppRegisterTxCallback(sdk_eapol_txcb, 3); } - -#endif /* OPEN_LIBWPA_WPA_MAIN */ diff --git a/tests/cases/03_byte_load_flash.c b/tests/cases/03_byte_load_flash.c index b8dcb8e..ccbe50e 100644 --- a/tests/cases/03_byte_load_flash.c +++ b/tests/cases/03_byte_load_flash.c @@ -290,7 +290,7 @@ static void a_03_byte_load_test_isr() printf("Testing behaviour inside ISRs...\r\n"); timer_set_interrupts(FRC1, false); timer_set_run(FRC1, false); - _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler); + _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL); timer_set_frequency(FRC1, 1000); timer_set_interrupts(FRC1, true); timer_set_run(FRC1, true); diff --git a/tests/cases/04_wifi_basic.c b/tests/cases/04_wifi_basic.c index 129ddd0..8deef3e 100644 --- a/tests/cases/04_wifi_basic.c +++ b/tests/cases/04_wifi_basic.c @@ -40,6 +40,11 @@ DEFINE_TESTCASE(04_wifi_basic, DUAL) static void server_task(void *pvParameters) { + + ip_addr_t first_client_ip; + IP4_ADDR(&first_client_ip, 172, 16, 0, 2); + dhcpserver_start(&first_client_ip, 4); + char buf[BUF_SIZE]; struct netconn *nc = netconn_new(NETCONN_TCP); TEST_ASSERT_TRUE_MESSAGE(nc != 0, "Failed to allocate socket"); @@ -103,10 +108,6 @@ static void a_04_wifi_basic(void) }; sdk_wifi_softap_set_config(&ap_config); - ip_addr_t first_client_ip; - IP4_ADDR(&first_client_ip, 172, 16, 0, 2); - dhcpserver_start(&first_client_ip, 4); - xTaskCreate(server_task, "setver_task", 1024, NULL, 2, NULL); }