Example #1
0
File: mu0.c Project: tessereth/mu0
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;
}
Example #2
0
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;
}