Make it easier to look up error messages

tools/gen_esp_err_to_name.py generates
components/esp32/esp_err_to_name.c for lookup of the error codes from
all of the IDF project and easily identify all codes in one place
This commit is contained in:
Roland Dobai 2018-02-01 13:14:47 +01:00
parent c3bec5b103
commit 4322e31c98
5 changed files with 793 additions and 0 deletions

View File

@ -319,6 +319,17 @@ test_report:
- git push origin master
- test "${TEST_RESULT}" = "Pass" || exit 1
test_esp_err_to_name_on_host:
stage: test
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
tags:
- build
dependencies: []
script:
- cd tools/
- ./gen_esp_err_to_name.py
- git diff --exit-code -- ../components/esp32/esp_err_to_name.c || (echo 'Differences found. Please run gen_esp_err_to_name.py and commit the changes.'; exit 1)
push_master_to_github:
stage: deploy
image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG

View File

@ -0,0 +1,396 @@
//Do not edit this file because it is autogenerated by gen_esp_err_to_name.py
#include <string.h>
#if __has_include("soc/soc.h")
#include "soc/soc.h"
#endif
#if __has_include("esp32/ulp.h")
#include "esp32/ulp.h"
#endif
#if __has_include("esp_err.h")
#include "esp_err.h"
#endif
#if __has_include("esp_image_format.h")
#include "esp_image_format.h"
#endif
#if __has_include("esp_now.h")
#include "esp_now.h"
#endif
#if __has_include("esp_ota_ops.h")
#include "esp_ota_ops.h"
#endif
#if __has_include("esp_ping.h")
#include "esp_ping.h"
#endif
#if __has_include("esp_spi_flash.h")
#include "esp_spi_flash.h"
#endif
#if __has_include("esp_wifi.h")
#include "esp_wifi.h"
#endif
#if __has_include("esp_wps.h")
#include "esp_wps.h"
#endif
#if __has_include("nvs.h")
#include "nvs.h"
#endif
#if __has_include("tcpip_adapter.h")
#include "tcpip_adapter.h"
#endif
#define ERR_TBL_IT(err) {err, #err}
typedef struct {
esp_err_t code;
const char *msg;
} esp_err_msg_t;
static const esp_err_msg_t esp_err_msg_table[] = {
// components/esp32/include/esp_err.h
# ifdef ESP_FAIL
ERR_TBL_IT(ESP_FAIL), /* -1 */
# endif
// components/esp32/include/esp_wifi.h
# ifdef ESP_ERR_WIFI_FAIL
ERR_TBL_IT(ESP_ERR_WIFI_FAIL), /* -1 General fail code */
# endif
// components/esp32/include/esp_err.h
# ifdef ESP_OK
ERR_TBL_IT(ESP_OK), /* 0 */
# endif
// components/esp32/include/esp_wifi.h
# ifdef ESP_ERR_WIFI_OK
ERR_TBL_IT(ESP_ERR_WIFI_OK), /* 0 No error */
# endif
// components/esp32/include/esp_err.h
# ifdef ESP_ERR_NO_MEM
ERR_TBL_IT(ESP_ERR_NO_MEM), /* 257 0x101 */
# endif
// components/esp32/include/esp_wifi.h
# ifdef ESP_ERR_WIFI_NO_MEM
ERR_TBL_IT(ESP_ERR_WIFI_NO_MEM), /* 257 0x101 Out of memory */
# endif
// components/esp32/include/esp_err.h
# ifdef ESP_ERR_INVALID_ARG
ERR_TBL_IT(ESP_ERR_INVALID_ARG), /* 258 0x102 */
# endif
// components/esp32/include/esp_wifi.h
# ifdef ESP_ERR_WIFI_ARG
ERR_TBL_IT(ESP_ERR_WIFI_ARG), /* 258 0x102 Invalid argument */
# endif
// components/esp32/include/esp_err.h
# ifdef ESP_ERR_INVALID_STATE
ERR_TBL_IT(ESP_ERR_INVALID_STATE), /* 259 0x103 */
# endif
# ifdef ESP_ERR_INVALID_SIZE
ERR_TBL_IT(ESP_ERR_INVALID_SIZE), /* 260 0x104 */
# endif
# ifdef ESP_ERR_NOT_FOUND
ERR_TBL_IT(ESP_ERR_NOT_FOUND), /* 261 0x105 */
# endif
# ifdef ESP_ERR_NOT_SUPPORTED
ERR_TBL_IT(ESP_ERR_NOT_SUPPORTED), /* 262 0x106 */
# endif
// components/esp32/include/esp_wifi.h
# ifdef ESP_ERR_WIFI_NOT_SUPPORT
ERR_TBL_IT(ESP_ERR_WIFI_NOT_SUPPORT), /* 262 0x106 Indicates that API is not supported yet */
# endif
// components/esp32/include/esp_err.h
# ifdef ESP_ERR_TIMEOUT
ERR_TBL_IT(ESP_ERR_TIMEOUT), /* 263 0x107 */
# endif
# ifdef ESP_ERR_INVALID_RESPONSE
ERR_TBL_IT(ESP_ERR_INVALID_RESPONSE), /* 264 0x108 */
# endif
# ifdef ESP_ERR_INVALID_CRC
ERR_TBL_IT(ESP_ERR_INVALID_CRC), /* 265 0x109 */
# endif
# ifdef ESP_ERR_INVALID_VERSION
ERR_TBL_IT(ESP_ERR_INVALID_VERSION), /* 266 0x10a */
# endif
# ifdef ESP_ERR_INVALID_MAC
ERR_TBL_IT(ESP_ERR_INVALID_MAC), /* 267 0x10b */
# endif
// components/nvs_flash/include/nvs.h
# ifdef ESP_ERR_NVS_BASE
ERR_TBL_IT(ESP_ERR_NVS_BASE), /* 4352 0x1100 Starting number of error codes */
# endif
# ifdef ESP_ERR_NVS_NOT_INITIALIZED
ERR_TBL_IT(ESP_ERR_NVS_NOT_INITIALIZED), /* 4353 0x1101 The storage driver is not initialized */
# endif
# ifdef ESP_ERR_NVS_NOT_FOUND
ERR_TBL_IT(ESP_ERR_NVS_NOT_FOUND), /* 4354 0x1102 Id namespace doesnt exist yet and mode is
NVS_READONLY */
# endif
# ifdef ESP_ERR_NVS_TYPE_MISMATCH
ERR_TBL_IT(ESP_ERR_NVS_TYPE_MISMATCH), /* 4355 0x1103 The type of set or get operation doesn't
match the type of value stored in NVS */
# endif
# ifdef ESP_ERR_NVS_READ_ONLY
ERR_TBL_IT(ESP_ERR_NVS_READ_ONLY), /* 4356 0x1104 Storage handle was opened as read only */
# endif
# ifdef ESP_ERR_NVS_NOT_ENOUGH_SPACE
ERR_TBL_IT(ESP_ERR_NVS_NOT_ENOUGH_SPACE), /* 4357 0x1105 There is not enough space in the underlying
storage to save the value */
# endif
# ifdef ESP_ERR_NVS_INVALID_NAME
ERR_TBL_IT(ESP_ERR_NVS_INVALID_NAME), /* 4358 0x1106 Namespace name doesnt satisfy constraints */
# endif
# ifdef ESP_ERR_NVS_INVALID_HANDLE
ERR_TBL_IT(ESP_ERR_NVS_INVALID_HANDLE), /* 4359 0x1107 Handle has been closed or is NULL */
# endif
# ifdef ESP_ERR_NVS_REMOVE_FAILED
ERR_TBL_IT(ESP_ERR_NVS_REMOVE_FAILED), /* 4360 0x1108 The value wasnt updated because flash
write operation has failed. The value was
written however, and update will be finished
after re-initialization of nvs, provided
that flash operation doesnt fail again. */
# endif
# ifdef ESP_ERR_NVS_KEY_TOO_LONG
ERR_TBL_IT(ESP_ERR_NVS_KEY_TOO_LONG), /* 4361 0x1109 Key name is too long */
# endif
# ifdef ESP_ERR_NVS_PAGE_FULL
ERR_TBL_IT(ESP_ERR_NVS_PAGE_FULL), /* 4362 0x110a Internal error; never returned by nvs_ API
functions */
# endif
# ifdef ESP_ERR_NVS_INVALID_STATE
ERR_TBL_IT(ESP_ERR_NVS_INVALID_STATE), /* 4363 0x110b NVS is in an inconsistent state due to a
previous error. Call nvs_flash_init and
nvs_open again, then retry. */
# endif
# ifdef ESP_ERR_NVS_INVALID_LENGTH
ERR_TBL_IT(ESP_ERR_NVS_INVALID_LENGTH), /* 4364 0x110c String or blob length is not sufficient to
store data */
# endif
# ifdef ESP_ERR_NVS_NO_FREE_PAGES
ERR_TBL_IT(ESP_ERR_NVS_NO_FREE_PAGES), /* 4365 0x110d NVS partition doesn't contain any empty
pages. This may happen if NVS partition was
truncated. Erase the whole partition and
call nvs_flash_init again. */
# endif
# ifdef ESP_ERR_NVS_VALUE_TOO_LONG
ERR_TBL_IT(ESP_ERR_NVS_VALUE_TOO_LONG), /* 4366 0x110e String or blob length is longer than
supported by the implementation */
# endif
# ifdef ESP_ERR_NVS_PART_NOT_FOUND
ERR_TBL_IT(ESP_ERR_NVS_PART_NOT_FOUND), /* 4367 0x110f Partition with specified name is not found
in the partition table */
# endif
// components/ulp/include/esp32/ulp.h
# ifdef ESP_ERR_ULP_BASE
ERR_TBL_IT(ESP_ERR_ULP_BASE), /* 4608 0x1200 Offset for ULP-related error codes */
# endif
# ifdef ESP_ERR_ULP_SIZE_TOO_BIG
ERR_TBL_IT(ESP_ERR_ULP_SIZE_TOO_BIG), /* 4609 0x1201 Program doesn't fit into RTC memory reserved
for the ULP */
# endif
# ifdef ESP_ERR_ULP_INVALID_LOAD_ADDR
ERR_TBL_IT(ESP_ERR_ULP_INVALID_LOAD_ADDR), /* 4610 0x1202 Load address is outside of RTC memory
reserved for the ULP */
# endif
# ifdef ESP_ERR_ULP_DUPLICATE_LABEL
ERR_TBL_IT(ESP_ERR_ULP_DUPLICATE_LABEL), /* 4611 0x1203 More than one label with the same number was
defined */
# endif
# ifdef ESP_ERR_ULP_UNDEFINED_LABEL
ERR_TBL_IT(ESP_ERR_ULP_UNDEFINED_LABEL), /* 4612 0x1204 Branch instructions references an undefined label */
# endif
# ifdef ESP_ERR_ULP_BRANCH_OUT_OF_RANGE
ERR_TBL_IT(ESP_ERR_ULP_BRANCH_OUT_OF_RANGE), /* 4613 0x1205 Branch target is out of range of B
instruction (try replacing with BX) */
# endif
// components/app_update/include/esp_ota_ops.h
# ifdef ESP_ERR_OTA_BASE
ERR_TBL_IT(ESP_ERR_OTA_BASE), /* 5376 0x1500 Base error code for ota_ops api */
# endif
# ifdef ESP_ERR_OTA_PARTITION_CONFLICT
ERR_TBL_IT(ESP_ERR_OTA_PARTITION_CONFLICT), /* 5377 0x1501 Error if request was to write or erase the
current running partition */
# endif
# ifdef ESP_ERR_OTA_SELECT_INFO_INVALID
ERR_TBL_IT(ESP_ERR_OTA_SELECT_INFO_INVALID), /* 5378 0x1502 Error if OTA data partition contains invalid
content */
# endif
# ifdef ESP_ERR_OTA_VALIDATE_FAILED
ERR_TBL_IT(ESP_ERR_OTA_VALIDATE_FAILED), /* 5379 0x1503 Error if OTA app image is invalid */
# endif
// components/bootloader_support/include/esp_image_format.h
# ifdef ESP_ERR_IMAGE_BASE
ERR_TBL_IT(ESP_ERR_IMAGE_BASE), /* 8192 0x2000 */
# endif
# ifdef ESP_ERR_IMAGE_FLASH_FAIL
ERR_TBL_IT(ESP_ERR_IMAGE_FLASH_FAIL), /* 8193 0x2001 */
# endif
# ifdef ESP_ERR_IMAGE_INVALID
ERR_TBL_IT(ESP_ERR_IMAGE_INVALID), /* 8194 0x2002 */
# endif
// components/esp32/include/esp_err.h
# ifdef ESP_ERR_WIFI_BASE
ERR_TBL_IT(ESP_ERR_WIFI_BASE), /* 12288 0x3000 Starting number of WiFi error codes */
# endif
// components/esp32/include/esp_wifi.h
# ifdef ESP_ERR_WIFI_NOT_INIT
ERR_TBL_IT(ESP_ERR_WIFI_NOT_INIT), /* 12289 0x3001 WiFi driver was not installed by esp_wifi_init */
# endif
# ifdef ESP_ERR_WIFI_NOT_STARTED
ERR_TBL_IT(ESP_ERR_WIFI_NOT_STARTED), /* 12290 0x3002 WiFi driver was not started by esp_wifi_start */
# endif
# ifdef ESP_ERR_WIFI_NOT_STOPPED
ERR_TBL_IT(ESP_ERR_WIFI_NOT_STOPPED), /* 12291 0x3003 WiFi driver was not stopped by esp_wifi_stop */
# endif
# ifdef ESP_ERR_WIFI_IF
ERR_TBL_IT(ESP_ERR_WIFI_IF), /* 12292 0x3004 WiFi interface error */
# endif
# ifdef ESP_ERR_WIFI_MODE
ERR_TBL_IT(ESP_ERR_WIFI_MODE), /* 12293 0x3005 WiFi mode error */
# endif
# ifdef ESP_ERR_WIFI_STATE
ERR_TBL_IT(ESP_ERR_WIFI_STATE), /* 12294 0x3006 WiFi internal state error */
# endif
# ifdef ESP_ERR_WIFI_CONN
ERR_TBL_IT(ESP_ERR_WIFI_CONN), /* 12295 0x3007 WiFi internal control block of station or
soft-AP error */
# endif
# ifdef ESP_ERR_WIFI_NVS
ERR_TBL_IT(ESP_ERR_WIFI_NVS), /* 12296 0x3008 WiFi internal NVS module error */
# endif
# ifdef ESP_ERR_WIFI_MAC
ERR_TBL_IT(ESP_ERR_WIFI_MAC), /* 12297 0x3009 MAC address is invalid */
# endif
# ifdef ESP_ERR_WIFI_SSID
ERR_TBL_IT(ESP_ERR_WIFI_SSID), /* 12298 0x300a SSID is invalid */
# endif
# ifdef ESP_ERR_WIFI_PASSWORD
ERR_TBL_IT(ESP_ERR_WIFI_PASSWORD), /* 12299 0x300b Password is invalid */
# endif
# ifdef ESP_ERR_WIFI_TIMEOUT
ERR_TBL_IT(ESP_ERR_WIFI_TIMEOUT), /* 12300 0x300c Timeout error */
# endif
# ifdef ESP_ERR_WIFI_WAKE_FAIL
ERR_TBL_IT(ESP_ERR_WIFI_WAKE_FAIL), /* 12301 0x300d WiFi is in sleep state(RF closed) and wakeup fail */
# endif
# ifdef ESP_ERR_WIFI_WOULD_BLOCK
ERR_TBL_IT(ESP_ERR_WIFI_WOULD_BLOCK), /* 12302 0x300e The caller would block */
# endif
# ifdef ESP_ERR_WIFI_NOT_CONNECT
ERR_TBL_IT(ESP_ERR_WIFI_NOT_CONNECT), /* 12303 0x300f Station still in disconnect status */
# endif
// components/esp32/include/esp_wps.h
# ifdef ESP_ERR_WIFI_REGISTRAR
ERR_TBL_IT(ESP_ERR_WIFI_REGISTRAR), /* 12339 0x3033 WPS registrar is not supported */
# endif
# ifdef ESP_ERR_WIFI_WPS_TYPE
ERR_TBL_IT(ESP_ERR_WIFI_WPS_TYPE), /* 12340 0x3034 WPS type error */
# endif
# ifdef ESP_ERR_WIFI_WPS_SM
ERR_TBL_IT(ESP_ERR_WIFI_WPS_SM), /* 12341 0x3035 WPS state machine is not initialized */
# endif
// components/esp32/include/esp_now.h
# ifdef ESP_ERR_ESPNOW_NOT_INIT
ERR_TBL_IT(ESP_ERR_ESPNOW_NOT_INIT), /* 12389 0x3065 ESPNOW is not initialized. */
# endif
# ifdef ESP_ERR_ESPNOW_BASE
ERR_TBL_IT(ESP_ERR_ESPNOW_BASE), /* 12389 0x3065 ESPNOW error number base. */
# endif
# ifdef ESP_ERR_ESPNOW_ARG
ERR_TBL_IT(ESP_ERR_ESPNOW_ARG), /* 12390 0x3066 Invalid argument */
# endif
# ifdef ESP_ERR_ESPNOW_NO_MEM
ERR_TBL_IT(ESP_ERR_ESPNOW_NO_MEM), /* 12391 0x3067 Out of memory */
# endif
# ifdef ESP_ERR_ESPNOW_FULL
ERR_TBL_IT(ESP_ERR_ESPNOW_FULL), /* 12392 0x3068 ESPNOW peer list is full */
# endif
# ifdef ESP_ERR_ESPNOW_NOT_FOUND
ERR_TBL_IT(ESP_ERR_ESPNOW_NOT_FOUND), /* 12393 0x3069 ESPNOW peer is not found */
# endif
# ifdef ESP_ERR_ESPNOW_INTERNAL
ERR_TBL_IT(ESP_ERR_ESPNOW_INTERNAL), /* 12394 0x306a Internal error */
# endif
# ifdef ESP_ERR_ESPNOW_EXIST
ERR_TBL_IT(ESP_ERR_ESPNOW_EXIST), /* 12395 0x306b ESPNOW peer has existed */
# endif
# ifdef ESP_ERR_ESPNOW_IF
ERR_TBL_IT(ESP_ERR_ESPNOW_IF), /* 12396 0x306c Interface error */
# endif
// components/tcpip_adapter/include/tcpip_adapter.h
# ifdef ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS), /* 20480 0x5000 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_BASE
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_BASE), /* 20480 0x5000 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY), /* 20481 0x5001 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED), /* 20482 0x5002 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED), /* 20483 0x5003 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED), /* 20484 0x5004 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_NO_MEM
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_NO_MEM), /* 20485 0x5005 */
# endif
# ifdef ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED
ERR_TBL_IT(ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED), /* 20486 0x5006 */
# endif
// components/lwip/apps/ping/esp_ping.h
# ifdef ESP_ERR_PING_INVALID_PARAMS
ERR_TBL_IT(ESP_ERR_PING_INVALID_PARAMS), /* 24576 0x6000 */
# endif
# ifdef ESP_ERR_PING_BASE
ERR_TBL_IT(ESP_ERR_PING_BASE), /* 24576 0x6000 */
# endif
# ifdef ESP_ERR_PING_NO_MEM
ERR_TBL_IT(ESP_ERR_PING_NO_MEM), /* 24577 0x6001 */
# endif
// components/spi_flash/include/esp_spi_flash.h
# ifdef ESP_ERR_FLASH_BASE
ERR_TBL_IT(ESP_ERR_FLASH_BASE), /* 65552 0x10010 */
# endif
# ifdef ESP_ERR_FLASH_OP_FAIL
ERR_TBL_IT(ESP_ERR_FLASH_OP_FAIL), /* 65553 0x10011 */
# endif
# ifdef ESP_ERR_FLASH_OP_TIMEOUT
ERR_TBL_IT(ESP_ERR_FLASH_OP_TIMEOUT), /* 65554 0x10012 */
# endif
};
static const char esp_unknown_msg[] = "UNKNOWN ERROR";
const char *esp_err_to_name(esp_err_t code)
{
int i;
for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
if (esp_err_msg_table[i].code == code) {
return esp_err_msg_table[i].msg;
}
}
return esp_unknown_msg;
}
const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen)
{
int i;
for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
if (esp_err_msg_table[i].code == code) {
strlcpy(buf, esp_err_msg_table[i].msg, buflen);
return buf;
}
}
if (strerror_r(code, buf, buflen) == 0) {
return buf;
}
snprintf(buf, buflen, "Unknown error %d", code);
return buf;
}

View File

@ -0,0 +1,53 @@
@COMMENT@
#include <string.h>
#if __has_include("soc/soc.h")
#include "soc/soc.h"
#endif
@HEADERS@
#define ERR_TBL_IT(err) {err, #err}
typedef struct {
esp_err_t code;
const char *msg;
} esp_err_msg_t;
static const esp_err_msg_t esp_err_msg_table[] = {
@ERROR_ITEMS@
};
static const char esp_unknown_msg[] = "UNKNOWN ERROR";
const char *esp_err_to_name(esp_err_t code)
{
int i;
for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
if (esp_err_msg_table[i].code == code) {
return esp_err_msg_table[i].msg;
}
}
return esp_unknown_msg;
}
const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen)
{
int i;
for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
if (esp_err_msg_table[i].code == code) {
strlcpy(buf, esp_err_msg_table[i].msg, buflen);
return buf;
}
}
if (strerror_r(code, buf, buflen) == 0) {
return buf;
}
snprintf(buf, buflen, "Unknown error %d", code);
return buf;
}

View File

@ -42,6 +42,39 @@ typedef int32_t esp_err_t;
#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */
/**
* @brief Returns string for esp_err_t error codes
*
* This function finds the error code in a pre-generated lookup-table and
* returns its string representation.
*
* The function is generated by the Python script
* tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
* error is modified, created or removed from the IDF project.
*
* @param code esp_err_t error code
* @return string error message
*/
const char *esp_err_to_name(esp_err_t code);
/**
* @brief Returns string for esp_err_t and system error codes
*
* This function finds the error code in a pre-generated lookup-table of
* esp_err_t errors and returns its string representation. If the error code
* is not found then it is attempted to be found among system errors.
*
* The function is generated by the Python script
* tools/gen_esp_err_to_name.py which should be run each time an esp_err_t
* error is modified, created or removed from the IDF project.
*
* @param code esp_err_t error code
* @param[out] buf buffer where the error message should be written
* @param buflen Size of buffer buf. At most buflen bytes are written into the buf buffer (including the terminating null byte).
* @return buf containing the string error message
*/
const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen);
void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression) __attribute__((noreturn));
#ifndef __ASSERT_FUNC

300
tools/gen_esp_err_to_name.py Executable file
View File

@ -0,0 +1,300 @@
#!/usr/bin/env python
#
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import argparse
import mmap
import re
import fnmatch
import string
import collections
import textwrap
# list files here which should not be parsed
ignore_files = [ 'components/mdns/test_afl_fuzz_host/esp32_compat.h' ]
# macros from here have higher priorities in case of collisions
priority_headers = [ 'components/esp32/include/esp_err.h' ]
err_dict = collections.defaultdict(list) #identified errors are stored here; mapped by the error code
rev_err_dict = dict() #map of error string to error code
unproc_list = list() #errors with unknown codes which depend on other errors
class ErrItem:
"""
Contains information about the error:
- name - error string
- file - relative path inside the IDF project to the file which defines this error
- comment - (optional) comment for the error
- rel_str - (optional) error string which is a base for the error
- rel_off - (optional) offset in relation to the base error
"""
def __init__(self, name, file, comment, rel_str = "", rel_off = 0):
self.name = name
self.file = file
self.comment = comment
self.rel_str = rel_str
self.rel_off = rel_off
def __str__(self):
ret = self.name + " from " + self.file
if (self.rel_str != ""):
ret += " is (" + self.rel_str + " + " + str(self.rel_off) + ")"
if self.comment != "":
ret += " // " + self.comment
return ret
def __cmp__(self, other):
if self.file in priority_headers and other.file not in priority_headers:
return -1
elif self.file not in priority_headers and other.file in priority_headers:
return 1
base = "_BASE"
if self.file == other.file:
if self.name.endswith(base) and not(other.name.endswith(base)):
return 1
elif not(self.name.endswith(base)) and other.name.endswith(base):
return -1
self_key = self.file + self.name
other_key = other.file + other.name
if self_key < other_key:
return -1
elif self_key > other_key:
return 1
else:
return 0
class InputError(RuntimeError):
"""
Represents and error on the input
"""
def __init__(self, p, e):
super(InputError, self).__init__(p + ": " + e)
def process(line, idf_path):
"""
Process a line of text from file idf_path (relative to IDF project).
Fills the global list unproc_list and dictionaries err_dict, rev_err_dict
"""
if idf_path.endswith(".c"):
# We would not try to include a C file
raise InputError(idf_path, "This line should be in a header file: %s" % line)
words = re.split(r' +', line, 2)
# words[1] is the error name
# words[2] is the rest of the line (value, base + value, comment)
if len(words) < 2:
raise InputError(idf_path, "Error at line %s" % line)
line = ""
todo_str = words[2]
comment = ""
# identify possible comment
m = re.search(r'/\*!<(.+?(?=\*/))', todo_str)
if m:
comment = string.strip(m.group(1))
todo_str = string.strip(todo_str[:m.start()]) # keep just the part before the comment
# identify possible parentheses ()
m = re.search(r'\((.+)\)', todo_str)
if m:
todo_str = m.group(1) #keep what is inside the parentheses
# identify BASE error code, e.g. from the form BASE + 0x01
m = re.search(r'\s*(\w+)\s*\+(.+)', todo_str)
if m:
related = m.group(1) # BASE
todo_str = m.group(2) # keep and process only what is after "BASE +"
# try to match a hexadecimal number
m = re.search(r'0x([0-9A-Fa-f]+)', todo_str)
if m:
num = int(m.group(1), 16)
else:
# Try to match a decimal number. Negative value is possible for some numbers, e.g. ESP_FAIL
m = re.search(r'(-?[0-9]+)', todo_str)
if m:
num = int(m.group(1), 10)
elif re.match(r'\w+', todo_str):
# It is possible that there is no number, e.g. #define ERROR BASE
related = todo_str # BASE error
num = 0 # (BASE + 0)
else:
raise InputError(idf_path, "Cannot parse line %s" % line)
try:
related
except NameError:
# The value of the error is known at this moment because it do not depends on some other BASE error code
err_dict[num].append(ErrItem(words[1], idf_path, comment))
rev_err_dict[words[1]] = num
else:
# Store the information available now and compute the error code later
unproc_list.append(ErrItem(words[1], idf_path, comment, related, num))
def process_remaining_errors():
"""
Create errors which could not be processed before because the error code
for the BASE error code wasn't known.
This works for sure only if there is no multiple-time dependency, e.g.:
#define BASE1 0
#define BASE2 (BASE1 + 10)
#define ERROR (BASE2 + 10) - ERROR will be processed successfully only if it processed later than BASE2
"""
for item in unproc_list:
if item.rel_str in rev_err_dict:
base_num = rev_err_dict[item.rel_str]
base = err_dict[base_num][0]
num = base_num + item.rel_off
err_dict[num].append(ErrItem(item.name, item.file, item.comment))
rev_err_dict[item.name] = num
else:
print(item.rel_str + " referenced by " + item.name + " in " + item.file + " is unknown")
del unproc_list[:]
def path_to_include(path):
"""
Process the path (relative to the IDF project) in a form which can be used
to include in a C file. Using just the filename does not work all the
time because some files are deeper in the tree. This approach tries to
find an 'include' parent directory an include its subdirectories, e.g.
"components/XY/include/esp32/file.h" will be transported into "esp32/file.h"
So this solution works only works when the subdirectory or subdirectories
are inside the "include" directory. Other special cases need to be handled
here when the compiler gives an unknown header file error message.
"""
spl_path = string.split(path, os.sep)
try:
i = spl_path.index('include')
except ValueError:
# no include in the path -> use just the filename
return os.path.basename(path)
else:
return str(os.sep).join(spl_path[i+1:]) # subdirectories and filename in "include"
def print_warning(error_list, error_code):
"""
Print warning about errors with the same error code
"""
print("[WARNING] The following errors have the same code (%d):" % error_code)
for e in error_list:
print(" " + str(e))
def max_string_width():
max = 0
for k in err_dict.keys():
for e in err_dict[k]:
x = len(e.name)
if x > max:
max = x
return max
def generate_output(fin, fout):
"""
Writes the output to fout based on th error dictionary err_dict and
template file fin.
"""
# make includes unique by using a set
includes = set()
for k in err_dict.keys():
for e in err_dict[k]:
includes.add(path_to_include(e.file))
# The order in a set in non-deterministic therefore it could happen that the
# include order will be different in other machines and false difference
# in the output file could be reported. In order to avoid this, the items
# are sorted in a list.
include_list = list(includes)
include_list.sort()
max_width = max_string_width() + 17 + 1 # length of " ERR_TBL_IT()," with spaces is 17
max_decdig = max(len(str(k)) for k in err_dict.keys())
for line in fin:
if re.match(r'@COMMENT@', line):
fout.write("//Do not edit this file because it is autogenerated by " + os.path.basename(__file__) + "\n")
elif re.match(r'@HEADERS@', line):
for i in include_list:
fout.write("#if __has_include(\"" + i + "\")\n#include \"" + i + "\"\n#endif\n")
elif re.match(r'@ERROR_ITEMS@', line):
last_file = ""
for k in sorted(err_dict.keys()):
if len(err_dict[k]) > 1:
err_dict[k].sort()
print_warning(err_dict[k], k)
for e in err_dict[k]:
if e.file != last_file:
last_file = e.file
fout.write(" // %s\n" % last_file)
table_line = (" ERR_TBL_IT(" + e.name + "), ").ljust(max_width) + "/* " + str(k).rjust(max_decdig)
fout.write("# ifdef %s\n" % e.name)
fout.write(table_line)
hexnum_length = 0
if k > 0: # negative number and zero should be only ESP_FAIL and ESP_OK
hexnum = " 0x%x" % k
hexnum_length = len(hexnum)
fout.write(hexnum)
if e.comment != "":
if len(e.comment) < 50:
fout.write(" %s" % e.comment)
else:
indent = " " * (len(table_line) + hexnum_length + 1)
w = textwrap.wrap(e.comment, width=120, initial_indent = indent, subsequent_indent = indent)
# this couldn't be done with initial_indent because there is no initial_width option
fout.write(" %s" % w[0].strip())
for i in range(1, len(w)):
fout.write("\n%s" % w[i])
fout.write(" */\n# endif\n")
else:
fout.write(line)
def main():
parser = argparse.ArgumentParser(description='ESP32 esp_err_to_name lookup generator for esp_err_t')
parser.add_argument('input', help='Path to the esp_err_to_name.c.in template input.', default=os.environ['IDF_PATH'] + '/components/esp32/esp_err_to_name.c.in', nargs='?')
parser.add_argument('output', help='Path to the esp_err_to_name.c output.', default=os.environ['IDF_PATH'] + '/components/esp32/esp_err_to_name.c', nargs='?')
args = parser.parse_args()
for root, dirnames, filenames in os.walk(os.environ['IDF_PATH']):
for filename in fnmatch.filter(filenames, '*.[ch]'):
full_path = os.path.join(root, filename)
idf_path = os.path.relpath(full_path, os.environ['IDF_PATH'])
if idf_path in ignore_files:
continue
with open(full_path, "r+b") as f:
try:
map = mmap.mmap(f.fileno(), 0, prot=mmap.ACCESS_READ)
except ValueError:
pass # An empty file cannot be mmaped
else:
for line in iter(map.readline, ""):
# match also ESP_OK and ESP_FAIL because some of ESP_ERRs are referencing them
if re.match(r"\s*#define\s+(ESP_ERR_|ESP_OK|ESP_FAIL)", line):
try:
process(str.strip(line), idf_path)
except InputError as e:
print (e)
process_remaining_errors()
with open(args.input, 'r') as fin, open(args.output, 'w') as fout:
generate_output(fin, fout)
if __name__ == "__main__":
main()