/* * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License * v. 1.0 which is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ /* * Launcher to run existing programs in the FreeRTOS+lwIP Simulator. * * Verification of FreeRTOS+lwIP compatibility in Continuous Integration (CI) * setups is another intended purpose. */ #include #include #include #include #include #include #if _WIN32 # define EX_OK (0) # define EX_USAGE (64) # define LF "\r\n" #else # include # define LF "\n" #endif #include #include /* Setup system hardware. */ void prvSetupHardware(void) { /* No hardware to setup when running in the simulator. */ return; } void vAssertCalled(unsigned long ulLine, const char * const pcFileName) { taskENTER_CRITICAL(); { fprintf(stderr, "[ASSERT] %s:%lu"LF, pcFileName, ulLine); } taskEXIT_CRITICAL(); abort(); } void vApplicationMallocFailedHook(void) { vAssertCalled(__LINE__, __FILE__); } void vApplicationIdleHook(void) { return; } void vApplicationTickHook( void ) { return; } static void usage(const char *name) { static const char fmt[] = "Usage: %s LAUNCHER_OPTIONS -- PROGRAM_OPTIONS"LF "Try '%s -h' for more information"LF; fprintf(stderr, fmt, name, name); } static void help(const char *name) { static const char fmt[] = "Usage: %s LAUNCHER_OPTIONS -- PROGRAM_OPTIONS"LF ""LF "Launcher options:"LF " -h Show this help message and exit"LF; fprintf(stdout, fmt, name); } typedef struct { int argc; char **argv; } args_t; extern int real_main(int argc, char *argv[]); static void vMainTask(void *ptr) { args_t *args = (args_t *)ptr; /* Reset getopt global variables. */ opterr = 1; optind = 1; (void)real_main(args->argc, args->argv); vPortFree(args->argv); vPortFree(args); vTaskDelete(NULL); _Exit(0); } int main(int argc, char *argv[]) { int opt; char *name; args_t *args = NULL; /* Determine program name. */ assert(argc >= 0 && argv[0] != NULL); name = strrchr(argv[0], '/'); if (name != NULL) { name++; } else { name = argv[0]; } if ((args = pvPortMalloc(sizeof(*args))) == NULL) { return EX_OSERR; } memset(args, 0, sizeof(*args)); /* Parse command line options. */ while ((opt = getopt(argc, argv, ":a:dg:hn:")) != -1) { switch (opt) { case 'h': help(name); exit(EX_OK); case '?': fprintf(stderr, "Unknown option '%c'"LF, opt); usage(name); exit(EX_USAGE); case ':': /* fall through */ default: fprintf(stderr, "Option '%c' requires an argument"LF, opt); usage(name); exit(EX_USAGE); } } /* Copy leftover arguments into a new array. */ args->argc = (argc - optind) + 1; args->argv = pvPortMalloc((args->argc + 1) * sizeof(*args->argv)); if (args->argv == NULL) { return EX_OSERR; } args->argv[0] = argv[0]; for (int i = optind, j = 1; i < argc; i++, j++) { args->argv[j] = argv[i]; } prvSetupHardware(); xTaskCreate(vMainTask, name, configMINIMAL_STACK_SIZE, args, (tskIDLE_PRIORITY + 1UL), (xTaskHandle *) NULL); vTaskStartScheduler(); return EX_SOFTWARE; }