void assemble(FILE *fin, FILE *fout, int verbose) { label_table_t *table; char line[LINE_SIZE]; int line_ok; table = generate_label_table(fin, verbose); /* Iterate through all the lines. This is full of pointer magic * which is why the code is so fragile. */ while (fgets(line, LINE_SIZE, fin) != NULL) { line_ok = 0; if (*line == LABEL_C || *line == COMMENT_C || isspace(*line)) { /* ignore line */ line_ok = 1; } else if (*line == NUM_LITERAL_C) { fprintf(fout, "%04lx\n", strtol(line+1, NULL, 0)); line_ok = 1; } else if (*line == CHAR_LITERAL_C) { fprintf(fout, "%04x\n", (int) line[1]); line_ok = 1; } else { line_ok = process_opcode(line, table, fout, verbose); } if (!line_ok) { fprintf(stderr, "Warning: Ignoring bad line: %s", line); } } free_table(table); return; }
static int adsi_process(struct adsi_script *state, char *buf, const char *script, int lineno) { char *keyword = get_token(&buf, script, lineno); char *args, vname[256], tmp[80], tmp2[80]; int lrci, wi, event; struct adsi_display *disp; struct adsi_subscript *newsub; if (!keyword) return 0; switch(state->state) { case STATE_NORMAL: if (!strcasecmp(keyword, "DESCRIPTION")) { if ((args = get_token(&buf, script, lineno))) { if (process_token(state->desc, args, sizeof(state->desc) - 1, ARG_STRING)) ast_log(LOG_WARNING, "'%s' is not a valid token for DESCRIPTION at line %d of %s\n", args, lineno, script); } else ast_log(LOG_WARNING, "Missing argument for DESCRIPTION at line %d of %s\n", lineno, script); } else if (!strcasecmp(keyword, "VERSION")) { if ((args = get_token(&buf, script, lineno))) { if (process_token(&state->ver, args, sizeof(state->ver) - 1, ARG_NUMBER)) ast_log(LOG_WARNING, "'%s' is not a valid token for VERSION at line %d of %s\n", args, lineno, script); } else ast_log(LOG_WARNING, "Missing argument for VERSION at line %d of %s\n", lineno, script); } else if (!strcasecmp(keyword, "SECURITY")) { if ((args = get_token(&buf, script, lineno))) { if (process_token(state->sec, args, sizeof(state->sec) - 1, ARG_STRING | ARG_NUMBER)) ast_log(LOG_WARNING, "'%s' is not a valid token for SECURITY at line %d of %s\n", args, lineno, script); } else ast_log(LOG_WARNING, "Missing argument for SECURITY at line %d of %s\n", lineno, script); } else if (!strcasecmp(keyword, "FDN")) { if ((args = get_token(&buf, script, lineno))) { if (process_token(state->fdn, args, sizeof(state->fdn) - 1, ARG_STRING | ARG_NUMBER)) ast_log(LOG_WARNING, "'%s' is not a valid token for FDN at line %d of %s\n", args, lineno, script); } else ast_log(LOG_WARNING, "Missing argument for FDN at line %d of %s\n", lineno, script); } else if (!strcasecmp(keyword, "KEY")) { if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "KEY definition missing name at line %d of %s\n", lineno, script); break; } if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script); break; } if (!(state->key = getkeybyname(state, vname, script, lineno))) { ast_log(LOG_WARNING, "Out of key space at line %d of %s\n", lineno, script); break; } if (state->key->defined) { ast_log(LOG_WARNING, "Cannot redefine key '%s' at line %d of %s\n", vname, lineno, script); break; } if (!(args = get_token(&buf, script, lineno)) || strcasecmp(args, "IS")) { ast_log(LOG_WARNING, "Expecting 'IS', but got '%s' at line %d of %s\n", args ? args : "<nothing>", lineno, script); break; } if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "KEY definition missing short name at line %d of %s\n", lineno, script); break; } if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY short name at line %d of %s\n", args, lineno, script); break; } if ((args = get_token(&buf, script, lineno))) { if (strcasecmp(args, "OR")) { ast_log(LOG_WARNING, "Expecting 'OR' but got '%s' instead at line %d of %s\n", args, lineno, script); break; } if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "KEY definition missing optional long name at line %d of %s\n", lineno, script); break; } if (process_token(tmp2, args, sizeof(tmp2) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY long name at line %d of %s\n", args, lineno, script); break; } } else { ast_copy_string(tmp2, tmp, sizeof(tmp2)); } if (strlen(tmp2) > 18) { ast_log(LOG_WARNING, "Truncating full name to 18 characters at line %d of %s\n", lineno, script); tmp2[18] = '\0'; } if (strlen(tmp) > 7) { ast_log(LOG_WARNING, "Truncating short name to 7 bytes at line %d of %s\n", lineno, script); tmp[7] = '\0'; } /* Setup initial stuff */ state->key->retstr[0] = 128; /* 1 has the length */ state->key->retstr[2] = state->key->id; /* Put the Full name in */ memcpy(state->key->retstr + 3, tmp2, strlen(tmp2)); /* Update length */ state->key->retstrlen = strlen(tmp2) + 3; /* Put trailing 0xff */ state->key->retstr[state->key->retstrlen++] = 0xff; /* Put the short name */ memcpy(state->key->retstr + state->key->retstrlen, tmp, strlen(tmp)); /* Update length */ state->key->retstrlen += strlen(tmp); /* Put trailing 0xff */ state->key->retstr[state->key->retstrlen++] = 0xff; /* Record initial length */ state->key->initlen = state->key->retstrlen; state->state = STATE_INKEY; } else if (!strcasecmp(keyword, "SUB")) { if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "SUB definition missing name at line %d of %s\n", lineno, script); break; } if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script); break; } if (!(state->sub = getsubbyname(state, vname, script, lineno))) { ast_log(LOG_WARNING, "Out of subroutine space at line %d of %s\n", lineno, script); break; } if (state->sub->defined) { ast_log(LOG_WARNING, "Cannot redefine subroutine '%s' at line %d of %s\n", vname, lineno, script); break; } /* Setup sub */ state->sub->data[0] = 130; /* 1 is the length */ state->sub->data[2] = 0x0; /* Clear extensibility bit */ state->sub->datalen = 3; if (state->sub->id) { /* If this isn't the main subroutine, make a subroutine label for it */ state->sub->data[3] = 9; state->sub->data[4] = state->sub->id; /* 5 is length */ state->sub->data[6] = 0xff; state->sub->datalen = 7; } if (!(args = get_token(&buf, script, lineno)) || strcasecmp(args, "IS")) { ast_log(LOG_WARNING, "Expecting 'IS', but got '%s' at line %d of %s\n", args ? args : "<nothing>", lineno, script); break; } state->state = STATE_INSUB; } else if (!strcasecmp(keyword, "STATE")) { if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "STATE definition missing name at line %d of %s\n", lineno, script); break; } if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a STATE name at line %d of %s\n", args, lineno, script); break; } if (getstatebyname(state, vname, script, lineno, 0)) { ast_log(LOG_WARNING, "State '%s' is already defined at line %d of %s\n", vname, lineno, script); break; } getstatebyname(state, vname, script, lineno, 1); } else if (!strcasecmp(keyword, "FLAG")) { if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "FLAG definition missing name at line %d of %s\n", lineno, script); break; } if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a FLAG name at line %d of %s\n", args, lineno, script); break; } if (getflagbyname(state, vname, script, lineno, 0)) { ast_log(LOG_WARNING, "Flag '%s' is already defined\n", vname); break; } getflagbyname(state, vname, script, lineno, 1); } else if (!strcasecmp(keyword, "DISPLAY")) { lrci = 0; wi = 0; if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "SUB definition missing name at line %d of %s\n", lineno, script); break; } if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script); break; } if (getdisplaybyname(state, vname, script, lineno, 0)) { ast_log(LOG_WARNING, "State '%s' is already defined\n", vname); break; } if (!(disp = getdisplaybyname(state, vname, script, lineno, 1))) break; if (!(args = get_token(&buf, script, lineno)) || strcasecmp(args, "IS")) { ast_log(LOG_WARNING, "Missing 'IS' at line %d of %s\n", lineno, script); break; } if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "Missing Column 1 text at line %d of %s\n", lineno, script); break; } if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "Token '%s' is not valid column 1 text at line %d of %s\n", args, lineno, script); break; } if (strlen(tmp) > 20) { ast_log(LOG_WARNING, "Truncating column one to 20 characters at line %d of %s\n", lineno, script); tmp[20] = '\0'; } memcpy(disp->data + 5, tmp, strlen(tmp)); disp->datalen = strlen(tmp) + 5; disp->data[disp->datalen++] = 0xff; args = get_token(&buf, script, lineno); if (args && !process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) { /* Got a column two */ if (strlen(tmp) > 20) { ast_log(LOG_WARNING, "Truncating column two to 20 characters at line %d of %s\n", lineno, script); tmp[20] = '\0'; } memcpy(disp->data + disp->datalen, tmp, strlen(tmp)); disp->datalen += strlen(tmp); args = get_token(&buf, script, lineno); } while (args) { if (!strcasecmp(args, "JUSTIFY")) { args = get_token(&buf, script, lineno); if (!args) { ast_log(LOG_WARNING, "Qualifier 'JUSTIFY' requires an argument at line %d of %s\n", lineno, script); break; } lrci = getjustifybyname(args); if (lrci < 0) { ast_log(LOG_WARNING, "'%s' is not a valid justification at line %d of %s\n", args, lineno, script); break; } } else if (!strcasecmp(args, "WRAP")) { wi = 0x80; } else { ast_log(LOG_WARNING, "'%s' is not a known qualifier at line %d of %s\n", args, lineno, script); break; } args = get_token(&buf, script, lineno); } if (args) { /* Something bad happened */ break; } disp->data[0] = 129; disp->data[1] = disp->datalen - 2; disp->data[2] = ((lrci & 0x3) << 6) | disp->id; disp->data[3] = wi; disp->data[4] = 0xff; } else { ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in PROGRAM\n", keyword); } break; case STATE_INKEY: if (process_returncode(state->key, keyword, buf, state, script, lineno)) { if (!strcasecmp(keyword, "ENDKEY")) { /* Return to normal operation and increment current key */ state->state = STATE_NORMAL; state->key->defined = 1; state->key->retstr[1] = state->key->retstrlen - 2; state->key = NULL; } else { ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in SOFTKEY definition at line %d of %s\n", keyword, lineno, script); } } break; case STATE_INIF: if (process_opcode(state->sub, keyword, buf, state, script, lineno)) { if (!strcasecmp(keyword, "ENDIF")) { /* Return to normal SUB operation and increment current key */ state->state = STATE_INSUB; state->sub->defined = 1; /* Store the proper number of instructions */ state->sub->ifdata[2] = state->sub->ifinscount; } else if (!strcasecmp(keyword, "GOTO")) { if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "GOTO clause missing Subscript name at line %d of %s\n", lineno, script); break; } if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) { ast_log(LOG_WARNING, "'%s' is not a valid subscript name token at line %d of %s\n", args, lineno, script); break; } if (!(newsub = getsubbyname(state, tmp, script, lineno))) break; /* Somehow you use GOTO to go to another place */ state->sub->data[state->sub->datalen++] = 0x8; state->sub->data[state->sub->datalen++] = state->sub->ifdata[1]; state->sub->data[state->sub->datalen++] = newsub->id; /* Terminate */ state->sub->data[state->sub->datalen++] = 0xff; /* Increment counters */ state->sub->inscount++; state->sub->ifinscount++; } else { ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in IF clause at line %d of %s\n", keyword, lineno, script); } } else state->sub->ifinscount++; break; case STATE_INSUB: if (process_opcode(state->sub, keyword, buf, state, script, lineno)) { if (!strcasecmp(keyword, "ENDSUB")) { /* Return to normal operation and increment current key */ state->state = STATE_NORMAL; state->sub->defined = 1; /* Store the proper length */ state->sub->data[1] = state->sub->datalen - 2; if (state->sub->id) { /* if this isn't main, store number of instructions, too */ state->sub->data[5] = state->sub->inscount; } state->sub = NULL; } else if (!strcasecmp(keyword, "IFEVENT")) { if (!(args = get_token(&buf, script, lineno))) { ast_log(LOG_WARNING, "IFEVENT clause missing Event name at line %d of %s\n", lineno, script); break; } if ((event = geteventbyname(args)) < 1) { ast_log(LOG_WARNING, "'%s' is not a valid event\n", args); break; } if (!(args = get_token(&buf, script, lineno)) || strcasecmp(args, "THEN")) { ast_log(LOG_WARNING, "IFEVENT clause missing 'THEN' at line %d of %s\n", lineno, script); break; } state->sub->ifinscount = 0; state->sub->ifdata = state->sub->data + state->sub->datalen; /* Reserve header and insert op codes */ state->sub->ifdata[0] = 0x1; state->sub->ifdata[1] = event; /* 2 is for the number of instructions */ state->sub->ifdata[3] = 0xff; state->sub->datalen += 4; /* Update Subscript instruction count */ state->sub->inscount++; state->state = STATE_INIF; } else { ast_log(LOG_WARNING, "Invalid or Unknown keyword '%s' in SUB definition at line %d of %s\n", keyword, lineno, script); } } break; default: ast_log(LOG_WARNING, "Can't process keyword '%s' in weird state %d\n", keyword, state->state); } return 0; }