/* Implements the ip address command. This function implements the "ipaddr" (ip address) set/display command. */ int cmd_static_ipaddr(int argc, char *argv[]) { tBoolean found; long lEEPROMRetStatus; unsigned short usdata,usdata2; char *param; if (argc < 2) { lEEPROMRetStatus = SoftEEPROMRead(STATIC_IPADDR_LOW_ID, &usdata, &found); if(lEEPROMRetStatus != 0) { cmd_print("\r\nAn error occurred during a soft EEPROM read operation"); return output_error(lEEPROMRetStatus); } if(found) { lEEPROMRetStatus = SoftEEPROMRead(STATIC_IPADDR_HIGH_ID, &usdata2, &found); cmd_print("\r\nip addr: %d.%d.%d.%d", ((usdata2 >> 8) & 0xff),((usdata2 >> 0) & 0xff),((usdata >> 8) & 0xff),((usdata >> 0) & 0xff)); lEEPROMRetStatus = SoftEEPROMRead(STATIC_IPMASK_LOW_ID, &usdata, &found); lEEPROMRetStatus = SoftEEPROMRead(STATIC_IPMASK_HIGH_ID, &usdata2, &found); cmd_print("\r\nmask : %d.%d.%d.%d", ((usdata2 >> 8) & 0xff),((usdata2 >> 0) & 0xff),((usdata >> 8) & 0xff),((usdata >> 0) & 0xff)); lEEPROMRetStatus = SoftEEPROMRead(STATIC_IPGW_LOW_ID, &usdata, &found); lEEPROMRetStatus = SoftEEPROMRead(STATIC_IPGW_HIGH_ID, &usdata2, &found); cmd_print("\r\ngateway: %d.%d.%d.%d", ((usdata2 >> 8) & 0xff),((usdata2 >> 0) & 0xff),((usdata >> 8) & 0xff),((usdata >> 0) & 0xff)); return(0); } cmd_print("\r\nNo static ip address stored."); } else if (argc == 5){
int cmd_module(int argc, char *argv[]) { struct module_info *header; header = (struct module_info *)pvPortMalloc(sizeof(struct module_info)); if (argc < 2) { cmd_print("\r\ni2c exists: %d",I2CEE_exists(SLAVE_ADDRESS_MODULE1)); } else { if(ustrncmp(argv[1],"write",5) == 0) { header->magic = 0x3A; header->vendor = 0x01; header->product = 0x01; header->version = 0x01; header->profile = ustrtoul(argv[2],NULL,16); header->modres = ustrtoul(argv[3],NULL,16); header->dummy2 = 0; header->crc = crcSlow((unsigned char *)header, sizeof(struct module_info)-sizeof(header->crc)); I2CEE_write(SLAVE_ADDRESS_MODULE1,(unsigned char *) header, sizeof(struct module_info), 0); vTaskDelay(100 / portTICK_RATE_MS); // there must be a delay after write or avoid I2CEE_read() } I2CEE_read(SLAVE_ADDRESS_MODULE1, (unsigned char *) header, sizeof(struct module_info), 0); cmd_print("\r\ni2c module magic: %X vendor: %X product: %X version: %X profile: %X modres: %X", header->magic, header->vendor, header->product, header->version, header->profile, header->modres); } vPortFree(header); return(0); }
/* This function prints out some module stats */ int cmd_stats(int argc, char *argv[]) { struct uart_info *uart_config; struct crc_info *crc_config; struct relay_info *relay_config; char buf[3]; for(size_t i = MODULE1; i <= MODULE4; i++) { if(module_exists(i)) { switch (module_profile_id(i)) { case PROFILE_UART: { uart_config = get_uart_profile(i); cmd_print("\r\nmodule id: %d base: %X port: %d rcv: %d sent: %d err: %d lost: %d buf: %d profile: ", i, uart_config->base, uart_config->port,uart_config->recv, uart_config->sent, uart_config->err, uart_config->lost,uart_config->buf_size * UART_QUEUE_SIZE); usnprintf((char *)&buf, 3, "%d",i+1); argc=2; argv[1]=(char *)&buf; read_uartmode(argc,argv); break;} case PROFILE_CRC: { crc_config = get_crc_profile(i); cmd_print("\r\nmodule id: %d profile: %s crc: %X crc2: %X", i, "crc error", crc_config->crc,crc_config->crc2); break;} case PROFILE_RELAY: { relay_config = get_relay_profile(i); cmd_print("\r\nmodule id: %d profile: %s start_value: %d negation: %d convert: %d", i, "relay", relay_config->start_value, relay_config->negation, relay_config->convert); break; } }; } else { cmd_print("\r\nmodule id: %d not available", i); } } return(0); }
/***************************************************************************** ! Outputs the error. ! ! This function will output an error message for the given error code and ! enter an infinite loop. The message is sent out via UART0. ! ! \param ulError is the error code returned by the soft EEPROM drivers. ! ! \return ERROR_MEM. *****************************************************************************/ int output_error(unsigned long ulError) { // // Switch and output based on the error code. // switch(ulError & 0x7FFF) { case ERR_NOT_INIT: cmd_print("\r\nERROR: Soft EEPROM not initialized!"); break; case ERR_ILLEGAL_ID: cmd_print("\r\nERROR: Illegal ID used!"); break; case ERR_PG_ERASE: cmd_print("\r\nERROR: Soft EEPROM page erase error!"); break; case ERR_PG_WRITE: cmd_print("\r\nERROR: Soft EEPROM page write error!"); break; case ERR_ACTIVE_PG_CNT: cmd_print("\r\nERROR: Active soft EEPROM page count error!"); break; case ERR_RANGE: cmd_print("\r\nERROR: Soft EEPROM specified out of range!"); break; case ERR_AVAIL_ENTRY: cmd_print("\r\nERROR: Next available entry error!"); break; case ERR_TWO_ACTIVE_NO_FULL: cmd_print("\r\nERROR: Two active pages found but not full!"); break; default: cmd_print("\r\nERROR: Unidentified Error"); break; } // // Did the error occur during the swap operation? // if(ulError & ERR_SWAP) { // // Indicate that the error occurred during the swap operation. // cmd_print("\r\nOccurred during the swap operation."); } return ERROR_MEM; }
static int red_cmd(char *cmd) { char *arg = cmd+1; SKIPSPACES(arg); switch(*cmd) { case 'q': return 0; case ';': case '#': break; // comment case '>': return cmd_dump(arg); break; case '<': return cmd_load(arg); break; case '.': return red_interpret(arg); break; case 's': return cmd_seek(arg); break; case 'b': return cmd_bsize(arg); break; case '/': return cmd_search(arg); break; case 'd': return cmd_system ("echo X | ired -n $BLOCK | rasm2 -o $OFFSET -D - |head -n $(($LINES-1))"); case 'p': return cmd_print(arg); break; case 'r': return cmd_resize(arg); break; case 'x': return cmd_hexdump(arg); break; case 'X': return cmd_bytedump(arg); break; case 'w': return cmd_write(arg); break; case '!': return cmd_system(arg); break; case 'V': return cmd_system("vired $FILE"); break; case '?': return cmd_help(arg); break; default: fprintf(stderr, "? %s\n", cmd); } return 1; }
void cmd_print_text_multiline_formatted() { cmdObj_t *cmd = cmd_body; for (uint8_t i=0; i<CMD_BODY_LEN-1; i++) { if (cmd->type != TYPE_PARENT) { cmd_print(cmd);} cmd = cmd->nx; if (cmd->type == TYPE_EMPTY) { break;} } }
int cmd_clear(int argc, char *argv[]) { long lEEPROMRetStatus; lEEPROMRetStatus = SoftEEPROMClear(); if(lEEPROMRetStatus != 0) { cmd_print("\rAn error occurred during a soft EEPROM clear operation"); return output_error(lEEPROMRetStatus); } return(0); }
int cmd_relay(int argc, char *argv[]) { unsigned char pin,value; unsigned short module; module = MODULE1; if(!(module_exists(module) && (module_profile_id(module) == PROFILE_RELAY))) { cmd_print("No relay available."); return(0); } if (argc == 2) { pin = ustrtoul(argv[1],NULL,0); cmd_print("\r\nrelay module: %d pin: %d value: %d",module,pin, relay_read(module,pin)); } else if (argc == 3) { pin = ustrtoul(argv[1],NULL,0); value = ustrtoul(argv[2],NULL,16); relay_write(module,pin,value); } return(0); }
/* Run the database program interactively. Will repeatedly prompt for a command. */ void run_interactive() { printf("Welcome to FlatDB.\n"); printf("Copyright 2013 Oracle Corporation\n"); printf("\"We synergize your paradigms.\"\n"); printf("\n"); char path[255]; printf("Enter the location of the database file. It does not need to exist; a blank one will be created for you if necessary.\n> "); fgets(path, 255, stdin); char command = 0; do { printf("\n"); printf("Choose a command:\n"); printf(" _a_dd an entry\n"); printf(" _f_ind an ID\n"); printf(" _r_remove an entry\n"); printf(" _p_rint the database\n"); printf(" _q_uit the application\n"); printf("> "); command = fgetc(stdin); getchar(); printf("\n"); switch (command) { case 'a': cmd_add(path); break; case 'f': cmd_get(path); break; case 'r': cmd_remove(path); break; case 'p': cmd_print(path); break; default: break; } } while (command != 'q'); printf("Thank you. Goodbye.\n"); }
/* The parent part of the multiprocess demonstration. * Generates an argv array, then forks three processes and execs this program with the -w flag. * Waits for all children to terminate, then prints the database contents. * * argv: argument list passed into this program. */ void run_multiprocess(const char **argv) { char **args; args = (char**)malloc(sizeof(char*)*4); args[0] = argv[0]; args[1] = "-w"; args[2] = argv[2]; args[3] = (char *)0; int child1, child2, child3; if ((child1 = fork()) == 0) { execv(*args, args); } else if ((child2 = fork()) == 0) { execv(*args, args); } else if ((child3 = fork()) == 0) { execv(*args, args); } else { //sleep(1000); int status; int pid; int procs[3]; procs[0] = child1; procs[1] = child2; procs[2] = child3; while (1) { pid = wait(&status); if (pid == child1) { procs[0] = 0; } if (pid == child2) { procs[1] = 0; } if (pid == child3) { procs[2] = 0; } if (procs[0] == 0 && procs[1] == 0 && procs[2] == 0) { break; } } cmd_print(argv[2]); } }
void exec_command(char cmd, char *param) { switch(cmd){ case'Q':cmd_quit(); break; case'C':cmd_check(); break; case'P':cmd_print(atoi(param)); break; case'R':cmd_read(param); break; case'W':cmd_write(param); break; case'F':cmd_find(param); break; case'S':cmd_sort(atoi(param)); break; case'E':cmd_edit(); break; case'H':cmd_help(); break; default:fprintf(stderr,"error\n\n"); } printf(":"); }
size_t cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len) { struct cmd *cmd; size_t off; off = 0; TAILQ_FOREACH(cmd, cmdlist, qentry) { if (off >= len) break; off += cmd_print(cmd, buf + off, len - off); if (off >= len) break; if (TAILQ_NEXT(cmd, qentry) != NULL) off += xsnprintf(buf + off, len - off, " ; "); } return (off); }
void exec_command(char cmd, char *param) { switch (cmd) { case 'Q': cmd_quit(); break; case 'C': cmd_check(); break; case 'P': cmd_print(atoi(param)); break; case 'R': cmd_read(param); break; case 'W': cmd_write(param); break; case 'F': cmd_find(param); break; case 'S': cmd_sort(atoi(param)); break; case 'D': cmd_delete(param); break; case 'r': cmd_random(); break; case 'T': test(atoi(param)); break; default: fprintf(stderr, "Invalid command %c: ignored.\n", cmd); break; } }
/* The kickoff function for the multithreaded demo. * Creates a mutex, info for five threads (see thread_info struct above), and the threads themselves. * Joins to each thread when it finishes, then destroys the mutex and prints the database. * * path: the path to the database file. */ void run_threaded(char *path) { // APPROACH // // 1. Create the mutex that will protect the shared resource. // 2. Create each thread by building up the info struct and sending it in as the parameter // 3. Join to each thread to know when they have all finished. // 4. Destroy the mutex, as it is no longer needed. // 5. Print the database. // Various items needed to work with threads pthread_mutex_t lock; // The mutex. This will be shared amongst all threads. int num_threads = 5; // The number of threads. Collected here for convenience. pthread_t threads[num_threads]; // The threads themselves, or rather where they will go. thread_info about_threads[num_threads]; // Information about each thread. // Create the mutex, or die. if ((pthread_mutex_init(&lock, NULL)) != 0) { fprintf(stderr, "An error occurred when initializing the mutex.\n"); exit(1); } // Create each thread. If it fails just skip it. for (int i = 0; i < num_threads; i++) { about_threads[i].threadid = i; about_threads[i].path = path; about_threads[i].lock = &lock; if (pthread_create(&threads[i], NULL, &run_threaded_worker, (void *)&about_threads[i]) != 0) { fprintf(stderr, "Whoops, that thread didn't work. Skipping it.\n"); } } // Join each thread. Like waiting on process but easier. for (int i = 0; i < num_threads; i++) { pthread_join(threads[i], NULL); } // This mutex is over. pthread_mutex_destroy(&lock); // Show the result. cmd_print(path); }
//----------------------------------------------------------------------------- int main(void) { halInit(); chSysInit(); kuroBoxInit(); chprintf(prnt, "Starting... [%s] \n", BOARD_NAME); kbg_setLCDBacklight(1); memset(&factory_config, 0, sizeof(factory_config)); cmd_read(prnt, 0, NULL); cmd_print(prnt, 0, NULL); Thread * shelltp = NULL; while ( 1 ) { if (!shelltp) { shelltp = shellCreate(&shell_cfg, SHELL_WA_SIZE, NORMALPRIO); } else if (chThdTerminated(shelltp)) { chThdRelease(shelltp); shelltp = NULL; } } //-------------------------------------------------------------------------- // endless loop to say we've finished while(1) { kbg_setLED1(0); kbg_setLED2(0); kbg_setLED3(0); chThdSleepMilliseconds(200); kbg_setLED1(1); kbg_setLED2(1); kbg_setLED3(1); chThdSleepMilliseconds(200); } }
/** * Process input characters to the command system * * @param commands Commands container * @param ctxp Pointer to context for editor (optional) * @param key Input character * @param pf Print function * @param data Application data * * @return 0 if success, otherwise errorcode */ int cmd_process(struct commands *commands, struct cmd_ctx **ctxp, char key, struct re_printf *pf, void *data) { const struct cmd *cmd; if (!commands) return EINVAL; if (key == KEYCODE_NONE) { warning("cmd: process: illegal keycode NONE\n"); return EINVAL; } /* are we in edit-mode? */ if (ctxp && *ctxp) { if (key == KEYCODE_REL) return 0; return cmd_process_edit(commands, ctxp, key, pf, data); } cmd = cmd_find_by_key(commands, key); if (cmd) { struct cmd_arg arg; /* check for parameters */ if (cmd->flags & CMD_PRM) { int err = 0; if (ctxp) { err = ctx_alloc(ctxp, cmd); if (err) return err; } key = isdigit(key) ? key : KEYCODE_REL; return cmd_process_edit(commands, ctxp, key, pf, data); } arg.key = key; arg.prm = NULL; arg.complete = true; arg.data = data; return cmd->h(pf, &arg); } else if (key == LONG_PREFIX) { int err; err = re_hprintf(pf, "%c", LONG_PREFIX); if (err) return err; if (!ctxp) { warning("cmd: ctxp is required\n"); return EINVAL; } err = ctx_alloc(ctxp, cmd); if (err) return err; (*ctxp)->is_long = true; return 0; } else if (key == '\t') { return cmd_print_all(pf, commands, false, true, NULL, 0); } if (key == KEYCODE_REL) return 0; return cmd_print(pf, commands); }
int main(int argc, char *argv[]) { struct cmd cmd; if (argc < 4) { usage: fprintf(stderr, "usage: semc <path|semid and semnum> -o|r|p|m|w|t|g|s <cmdargs>\n" " EXAMPLES:\n" " open: semc /tmp/foo -o 1 1 777 250 99\n" /* argv: 0 1 2 3 4 5 6 7 */ " remove: semc 5441 I -r\n" " post: semc 5441 3 -p\n" "post multiple: semc 5441 3 -m 10\n" " wait: semc 5441 3 -w\n" " try wait: semc 5441 3 -t\n" " get: semc 5441 3 -g\n" " set: semc 5441 3 -s 99\n"); fputs("The -o command takes a path and command arguments O_CREAT and/or " "O_EXCL and/or 0, mode_t in octal, numsems, and the value with which " "the semaphore(s) should be initialize. All other commands take a semid " "and semnum but -r igores semnum.\n", stderr); return EXIT_FAILURE; } memset(&cmd, 0, sizeof cmd); /* Determine Command */ if (strcmp(argv[2], "-o") == 0) { cmd.cmd = CMD_OPEN; } else if (*argv[3] == '-') { char *ch = strchr(cmdflags, argv[3][1]); if (!ch) { fprintf(stderr, "Invalid option: %s\n", argv[2]); goto usage; } cmd.cmd = ch - cmdflags; } else { fprintf(stderr, "Invalid options\n"); goto usage; } /* Populate struct cmd with Arguments */ switch (cmd.cmd) { case CMD_OPEN: if (argc < 8) { fprintf(stderr, "Too few arguments for command\n"); goto usage; } cmd.path = argv[1]; if (*argv[3] == '1') cmd.oflags |= O_CREAT; if (*argv[4] == '1') cmd.oflags |= O_EXCL; { unsigned long mode; if ((mode = strtoul(argv[5], NULL, 8)) == ULONG_MAX) { ERR(errno, "strtoul"); goto usage; } cmd.mode = mode; } if ((unsigned long)(cmd.numsems = strtoul(argv[6], NULL, 0)) == ULONG_MAX) { ERR(errno, "strtoul"); goto usage; } if ((unsigned long)(cmd.value = strtoul(argv[7], NULL, 0)) == ULONG_MAX) { ERR(errno, "strtoul"); goto usage; } break; case CMD_POSTMULT: case CMD_SETVAL: if ((unsigned long)(cmd.value = strtoul(argv[4], NULL, 0)) == ULONG_MAX) { ERR(errno, "strtoul"); goto usage; } case CMD_REMOVE: case CMD_POST: case CMD_WAIT: case CMD_TRYWAIT: case CMD_GETVAL: if ((unsigned long)(cmd.semid = strtoul(argv[1], NULL, 0)) == ULONG_MAX || (unsigned long)(cmd.semnum = strtoul(argv[2], NULL, 0)) == ULONG_MAX) { ERR(errno, "strtoul"); goto usage; } } cmd_print(&cmd); /* Run the Command */ if (cmd_functions[cmd.cmd](&cmd) == -1) { fprintf(stderr, "Command failed\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }
int cmd_quit(int argc, char *argv[]) { cmd_print("\r\nBye."); return CMDLINE_QUIT; }
// Get a statement numvar getstatement(void) { numvar retval = 0; char *fetchmark; chkbreak(); //#define LINEMODE #ifdef LINEMODE if (sym == s_while) { // at this point sym is pointing at s_while, before the conditional expression // save fetchptr so we can restart parsing from here as the while iterates char *fetchmark = fetchptr; for (;;) { fetchptr = fetchmark; // restore to mark primec(); // set up for mr. getsym() getsym(); // fetch the start of the conditional if (!getnum()) { //longjmp(env, X_EXIT); // get the conditional; exit on false sym = s_eof; // we're finished here. move along. return; } if (sym != s_colon) expectedchar(':'); getsym(); // eat : getstatementlist(); } } else if (sym == s_if) { getsym(); // fetch the start of the conditional if (!getnum()) { //longjmp(env, X_EXIT); // get the conditional; exit on false sym = s_eof; return; } if (sym != s_colon) expectedchar(':'); getsym(); // eat : getstatementlist(); } // The switch statement: call one of N macros based on a selector value // switch <numval>: macroid1, macroid2,.., macroidN // numval < 0: numval = 0 // numval > N: numval = N else if (sym == s_switch) { getsym(); // eat "switch" numvar selector = getnum(); // evaluate the switch value if (selector < 0) selector = 0; if (sym != s_colon) expectedchar(':'); // we sit before the first macroid // scan and discard the <selector>'s worth of macro ids // that sit before the one we want for (;;) { getsym(); // get an id, sets symval to its eeprom addr as a side effect if (sym != s_macro) expected (6); // TODO: define M_macro instead of 6 getsym(); // eat id, get separator; assume symval is untouched if ((sym == s_semi) || (sym == s_eof)) break; // last case is default so we exit always if (sym != s_comma) expectedchar(','); if (!selector) break; // ok, this is the one we want to execute selector--; // one down... } // call the macro whose addr is squirreled in symval all this time // on return, the parser is ready to pick up where we left off domacrocall(symval); // scan past the rest of the unused switch options, if any // TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space while ((sym != s_semi) && (sym != s_eof)) getsym(); // scan to end of statement without executing } #else // new statement handling if (sym == s_while) { // at this point sym is pointing at s_while, before the conditional expression // save fetchptr so we can restart parsing from here as the while iterates fetchmark = fetchptr; for (;;) { fetchptr = fetchmark; // restore to mark primec(); // set up for mr. getsym() getsym(); // fetch the start of the conditional if (getnum()) { retval = getstatement(); if (sym == s_returning) break; // exit if we caught a return } else { skipstatement(); break; } } } else if (sym == s_if) { getsym(); // eat "if" if (getnum()) { retval = getstatement(); if (sym == s_else) { getsym(); // eat "else" skipstatement(); } } else { skipstatement(); if (sym == s_else) { getsym(); // eat "else" retval = getstatement(); } } } else if (sym == s_lcurly) { getsym(); // eat "{" while ((sym != s_eof) && (sym != s_returning) && (sym != s_rcurly)) retval = getstatement(); if (sym == s_rcurly) getsym(); // eat "}" } else if (sym == s_return) { getsym(); // eat "return" if ((sym != s_eof) && (sym != s_semi)) retval = getnum(); sym = s_returning; // signal we're returning up the line } else if (sym == s_switch) retval = getswitchstatement(); else if (sym == s_function) cmd_function(); #endif else if (sym == s_run) { // run macroname getsym(); if (sym != s_macro) unexpected(M_id); // address of macroid is in symval via parseid // check for [,snoozeintervalms] getsym(); // eat macroid to check for comma; symval untouched if (sym == s_comma) { vpush(symval); getsym(); // eat the comma getnum(); // get a number or else startTask(kludge(vpop()), expval); } else startTask(kludge(symval), 0); } else if (sym == s_stop) { getsym(); if (sym == s_mul) { // stop * stops all tasks initTaskList(); getsym(); } else if ((sym == s_semi) || (sym == s_eof)) { if (background) stopTask(curtask); // stop with no args stops the current task IF we're in back else initTaskList(); // in foreground, stop all } else stopTask(getnum()); } else if (sym == s_boot) reboot(); #if !defined(TINY85) else if (sym == s_rm) { // rm "sym" or rm * getsym(); if (sym == s_macro) { eraseentry(idbuf); } else if (sym == s_mul) nukeeeprom(); else if (sym != s_undef) expected(M_id); getsym(); } else if (sym == s_ps) { getsym(); showTaskList(); } else if (sym == s_peep) { getsym(); cmd_peep(); } else if (sym == s_ls) { getsym(); cmd_ls(); } else if (sym == s_help) { getsym(); cmd_help(); } else if (sym == s_print) { getsym(); cmd_print(); } else if (sym == s_semi) { ; } // ;) #endif #ifdef HEX_UPLOAD // a line beginning with a colon is treated as a hex record // containing data to upload to eeprom // // TODO: verify checksum // else if (sym == s_colon) { // fetchptr points at the byte count byte byteCount = gethex(2); // 2 bytes byte count int addr = gethex(4); // 4 bytes address byte recordType = gethex(2); // 2 bytes record type; now fetchptr -> data if (recordType == 1) reboot(); // reboot on EOF record (01) if (recordType != 0) return; // we only handle the data record (00) if (addr == 0) nukeeeprom(); // auto-clear eeprom on write to 0000 while (byteCount--) eewrite(addr++, gethex(2)); // update the eeprom gethex(2); // discard the checksum getsym(); // and re-prime the parser } #endif else getexpression(); if (sym == s_semi) getsym(); // eat trailing ';' return retval; }
// Get a statement numvar getstatement(void) { numvar retval = 0; //char *fetchmark; numvar fetchmark; chkbreak(); if (sym == s_while) { // at this point sym is pointing at s_while, before the conditional expression // save fetchptr so we can restart parsing from here as the while iterates //fetchmark = fetchptr; fetchmark = markparsepoint(); for (;;) { //fetchptr = fetchmark; // restore to mark //primec(); // set up for mr. getsym() returntoparsepoint(fetchmark, 0); getsym(); // fetch the start of the conditional if (getnum()) { retval = getstatement(); if (sym == s_returning) break; // exit if we caught a return } else { skipstatement(); break; } } } else if (sym == s_if) { getsym(); // eat "if" if (getnum()) { retval = getstatement(); if (sym == s_else) { getsym(); // eat "else" skipstatement(); } } else { skipstatement(); if (sym == s_else) { getsym(); // eat "else" retval = getstatement(); } } } else if (sym == s_lcurly) { getsym(); // eat "{" while ((sym != s_eof) && (sym != s_returning) && (sym != s_rcurly)) retval = getstatement(); if (sym == s_rcurly) getsym(); // eat "}" } else if (sym == s_return) { getsym(); // eat "return" if ((sym != s_eof) && (sym != s_semi)) retval = getnum(); sym = s_returning; // signal we're returning up the line } else if (sym == s_switch) retval = getswitchstatement(); else if (sym == s_function) cmd_function(); else if (sym == s_run) { // run macroname getsym(); if ((sym != s_script_eeprom) && (sym != s_script_progmem) && (sym != s_script_file)) unexpected(M_id); // address of macroid is in symval via parseid // check for [,snoozeintervalms] getsym(); // eat macroid to check for comma; symval untouched if (sym == s_comma) { vpush(symval); getsym(); // eat the comma getnum(); // get a number or else startTask(vpop(), expval); } else startTask(symval, 0); } else if (sym == s_stop) { getsym(); if (sym == s_mul) { // stop * stops all tasks initTaskList(); getsym(); } else if ((sym == s_semi) || (sym == s_eof)) { if (background) stopTask(curtask); // stop with no args stops the current task IF we're in back else initTaskList(); // in foreground, stop all } else stopTask(getnum()); } else if (sym == s_boot) reboot(); else if (sym == s_rm) { // rm "sym" or rm * getsym(); if (sym == s_script_eeprom) { eraseentry(idbuf); } else if (sym == s_mul) nukeeeprom(); else if (sym != s_undef) expected(M_id); getsym(); } else if (sym == s_ps) { getsym(); showTaskList(); } else if (sym == s_peep) { getsym(); cmd_peep(); } else if (sym == s_ls) { getsym(); cmd_ls(); } else if (sym == s_help) { getsym(); cmd_help(); } else if (sym == s_print) { getsym(); cmd_print(); } else if (sym == s_semi) { ; } // ;) #ifdef HEX_UPLOAD // a line beginning with a colon is treated as a hex record // containing data to upload to eeprom // // TODO: verify checksum // else if (sym == s_colon) { // fetchptr points at the byte count byte byteCount = gethex(2); // 2 bytes byte count int addr = gethex(4); // 4 bytes address byte recordType = gethex(2); // 2 bytes record type; now fetchptr -> data if (recordType == 1) reboot(); // reboot on EOF record (01) if (recordType != 0) return; // we only handle the data record (00) if (addr == 0) nukeeeprom(); // auto-clear eeprom on write to 0000 while (byteCount--) eewrite(addr++, gethex(2)); // update the eeprom gethex(2); // discard the checksum getsym(); // and re-prime the parser } #endif else getexpression(); if (sym == s_semi) getsym(); // eat trailing ';' return retval; }
// Get a statement void getstatement(void) { #if !defined(TINY85) chkbreak(); #endif if (sym == s_while) { // at this point sym is pointing at s_while, before the conditional expression // save fetchptr so we can restart parsing from here as the while iterates char *fetchmark = fetchptr; for (;;) { fetchptr = fetchmark; // restore to mark primec(); // set up for mr. getsym() getsym(); // fetch the start of the conditional if (!getnum()) { //longjmp(env, X_EXIT); // get the conditional; exit on false sym = s_eof; // we're finished here. move along. return; } if (sym != s_colon) expectedchar(':'); getsym(); // eat : getstatementlist(); } } else if (sym == s_if) { getsym(); // fetch the start of the conditional if (!getnum()) { //longjmp(env, X_EXIT); // get the conditional; exit on false sym = s_eof; return; } if (sym != s_colon) expectedchar(':'); getsym(); // eat : getstatementlist(); } #if SKETCH // The switch statement: call one of N macros based on a selector value // switch <numval>: macroid1, macroid2,.., macroidN // numval < 0: numval = 0 // numval > N: numval = N else if (sym == s_switch) { getsym(); // eat "switch" numvar selector = getnum(); // evaluate the switch value if (selector < 0) selector = 0; if (sym != s_colon) expectedchar(':'); // we sit before the first macroid // scan and discard the <selector>'s worth of macro ids // that sit before the one we want for (;;) { getsym(); // get an id, sets symval to its eeprom addr as a side effect if (sym != s_macro) expected (6); // TODO: define M_macro instead of 6 getsym(); // eat id, get separator; assume symval is untouched if ((sym == s_semi) || (sym == s_eof)) break; // last case is default so we exit always if (sym != s_comma) expectedchar(','); if (!selector) break; // ok, this is the one we want to execute selector--; // one down... } // call the macro whose addr is squirreled in symval all this time // on return, the parser is ready to pick up where we left off doMacroCall(symval); // scan past the rest of the unused switch options, if any // TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space while ((sym != s_semi) && (sym != s_eof)) getsym(); // scan to end of statement without executing } #endif else if ((sym == s_macro) || (sym == s_undef)) { // macro def or ref getsym(); // scan past macro name to next symbol: ; or := if (sym == s_define) { // macro definition: macroid := strvalue // to define the macro, we need to copy the id somewhere on the stack // to avoid having this local buffer in every getstatement stack frame, // we break out defineMacro here to a separate function that only eats that // stack in the case that a macro is being defined #ifdef TINY85 unexpected(M_defmacro); #else defineMacro(); #endif } else if ((sym == s_semi) || (sym == s_eof)) { // valid macro reference: let's call it #if SKETCH doMacroCall(symval); // parseid stashes the macro address in symval #else char op = sym; // save sym for restore expval = findKey(idbuf); // assumes id in idbuf isn't clobbered since getsym() above if (expval >= 0) { char *fetchmark = fetchptr; // save the current parse pointer // call the macro calleeprommacro(findend(expval)); // register the macro into the parser stream getsym(); getstatementlist(); // parse and execute the macro code here if (sym != s_eof) expected(M_eof); // restore parsing context so we can resume cleanly fetchptr = fetchmark; // restore pointer primec(); // and inchar sym = op; // restore saved sym: s_semi or s_eof } else unexpected(M_id); #endif } else expectedchar(';'); //else getexpression(); // assume it was macro1+32+macro2... } else if (sym == s_run) { // run macroname getsym(); if (sym != s_macro) unexpected(M_id); #if 0 // address of macroid is in symval via parseid startTask(kludge(symval)); getsym(); #else // address of macroid is in symval via parseid // check for [,snoozeintervalms] getsym(); // eat macroid to check for comma; symval untouched if (sym == s_comma) { vpush(symval); getsym(); // eat the comma getnum(); // get a number or else startTask(kludge(vpop()), expval); } else startTask(kludge(symval), 0); #endif } else if (sym == s_stop) { getsym(); if (sym == s_mul) { // stop * stops all tasks initTaskList(); getsym(); } else if ((sym == s_semi) || (sym == s_eof)) { if (background) stopTask(curtask); // stop with no args stops the current task IF we're in back else initTaskList(); // in foreground, stop all } else stopTask(getnum()); } else if (sym == s_boot) reboot(); #if !defined(TINY85) else if (sym == s_rm) { // rm "sym" or rm * getsym(); if (sym == s_macro) { eraseentry(idbuf); } else if (sym == s_mul) nukeeeprom(); else expected(M_id); getsym(); } else if (sym == s_ps) showTaskList(); else if (sym == s_peep) { getsym(); cmd_peep(); } else if (sym == s_ls) { getsym(); cmd_ls(); } else if (sym == s_help) { getsym(); cmd_help(); } else if (sym == s_print) { getsym(); cmd_print(); } #endif #ifdef HEX_UPLOAD // a line beginning with a colon is treated as a hex record // containing data to upload to eeprom // // TODO: verify checksum // else if (sym == s_colon) { // fetchptr points at the byte count byte byteCount = gethex(2); // 2 bytes byte count int addr = gethex(4); // 4 bytes address byte recordType = gethex(2); // 2 bytes record type; now fetchptr -> data if (recordType == 1) reboot(); // reboot on EOF record (01) if (recordType != 0) return; // we only handle the data record (00) if (addr == 0) nukeeeprom(); // auto-clear eeprom on write to 0000 while (byteCount--) eewrite(addr++, gethex(2)); // update the eeprom gethex(2); // discard the checksum getsym(); // and re-prime the parser } #endif else { getexpression(); } }
void cmd_print(command_t *cmd, int indent) { int argc, i; if (cmd == NULL) { printf("%*s[NULL]\n", indent, ""); return; } for (argc = 0; argc < MAXTOKENS && cmd->argv[argc]; argc++) /* do nothing */; // More than MAXTOKENS is an error assert(argc <= MAXTOKENS); printf("%*s[%d args", indent, "", argc); for (i = 0; i < argc; i++) printf(" \"%s\"", cmd->argv[i]); // Print redirections if (cmd->redirect_filename[STDIN_FILENO]) printf(" <%s", cmd->redirect_filename[STDIN_FILENO]); if (cmd->redirect_filename[STDOUT_FILENO]) printf(" >%s", cmd->redirect_filename[STDOUT_FILENO]); if (cmd->redirect_filename[STDERR_FILENO]) printf(" 2>%s", cmd->redirect_filename[STDERR_FILENO]); // Print the subshell command, if any if (cmd->subshell) { printf("\n"); cmd_print(cmd->subshell, indent + 2); } printf("] "); switch (cmd->controlop) { case TOK_SEMICOLON: printf(";"); break; case TOK_AMPERSAND: printf("&"); break; case TOK_PIPE: printf("|"); break; case TOK_DOUBLEAMP: printf("&&"); break; case TOK_DOUBLEPIPE: printf("||"); break; case TOK_END: // we write "END" as a dot printf("."); break; default: assert(0); } // Done! printf("\n"); // if next is NULL, then controlop should be CMD_END, CMD_BACKGROUND, // or CMD_SEMICOLON assert(cmd->next || cmd->controlop == CMD_END || cmd->controlop == CMD_BACKGROUND || cmd->controlop == CMD_SEMICOLON); if (cmd->next) cmd_print(cmd->next, indent); }