// it requires up to 8 integer expressions between 0 and 3
ULAS_ASMDIR_CHR,
// .rep <n>, <step>, <line>
- // repeats a line n times
+ // repeats a line n times
ULAS_ASMDIR_REP,
};
// -1 on error
int ulas_asmnext(FILE *dst, FILE *src, char *buf, int n);
int ulas_asm(FILE *dst, FILE *src);
+int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n);
// parses and executes a 32 bit signed int math expressions
int ulas_intexpr(const char **line, unsigned long n, int *rc);
return written;
}
+int ulas_asmdirrep(FILE *dst, FILE *src, const char **line, unsigned long n) {
+ int repval = 0;
+ int rc = 0;
+
+ ULAS_EVALEXPRS(repval = ulas_intexpr(line, n, &rc));
+ ulas_tok(&ulas.tok, line, n);
+ struct ulas_tok t =
+ ulas_totok(ulas.tok.buf, strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
+ if (rc == -1 || t.type != ',') {
+ ULASERR("Expected ,\n");
+ return 0;
+ }
+
+ int step = 0;
+ ULAS_EVALEXPRS(step = ulas_intexpr(line, n, &rc));
+ ulas_tok(&ulas.tok, line, n);
+ t = ulas_totok(ulas.tok.buf, strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
+ if (rc == -1 || t.type != ',') {
+ ULASERR("Expected ,\n");
+ return 0;
+ }
+
+ unsigned long argline_len = strlen(*line);
+
+ for (int i = 0; i < repval; i += step) {
+ rc = ulas_asmline(dst, src, *line, argline_len);
+ if (rc == -1) {
+ break;
+ }
+ }
+
+ *line += argline_len;
+ return rc;
+}
+
int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
// this buffer is written both to dst and to verbose output
char outbuf[ULAS_OUTBUFMAX];
}
if (ulas.tok.buf[0] == ULAS_TOK_ASMDIR_BEGIN) {
- const char *dirstrs[] = {ULAS_ASMSTR_ORG,
- ULAS_ASMSTR_SET,
- ULAS_ASMSTR_BYTE,
- ULAS_ASMSTR_STR,
- ULAS_ASMSTR_FILL,
- ULAS_ASMSTR_PAD,
- ULAS_ASMSTR_INCBIN,
- ULAS_ASMSTR_DEF,
- ULAS_ASMSTR_CHKSM,
- ULAS_ASMSTR_ADV,
- ULAS_ASMSTR_SET_ENUM_DEF,
- ULAS_ASMSTR_DEFINE_ENUM,
- ULAS_ASMSTR_SETCHRCODE,
- ULAS_ASMSTR_CHR,
- ULAS_ASMSTR_REP,
- NULL};
+ const char *dirstrs[] = {ULAS_ASMSTR_ORG, ULAS_ASMSTR_SET,
+ ULAS_ASMSTR_BYTE, ULAS_ASMSTR_STR,
+ ULAS_ASMSTR_FILL, ULAS_ASMSTR_PAD,
+ ULAS_ASMSTR_INCBIN, ULAS_ASMSTR_DEF,
+ ULAS_ASMSTR_CHKSM, ULAS_ASMSTR_ADV,
+ ULAS_ASMSTR_SET_ENUM_DEF, ULAS_ASMSTR_DEFINE_ENUM,
+ ULAS_ASMSTR_SETCHRCODE, ULAS_ASMSTR_CHR,
+ ULAS_ASMSTR_REP, NULL};
enum ulas_asmdir dirs[] = {
ULAS_ASMDIR_ORG, ULAS_ASMDIR_SET,
ULAS_ASMDIR_BYTE, ULAS_ASMDIR_STR,
ULAS_ASMDIR_INCBIN, ULAS_ASMDIR_DEF,
ULAS_ASMDIR_CHKSM, ULAS_ASMDIR_ADV,
ULAS_ASMDIR_SET_ENUM_DEF, ULAS_ASMDIR_DEFINE_ENUM,
- ULAS_ASMDIR_SETCHRCODE, ULAS_ASMDIR_CHR, ULAS_ASMDIR_REP};
+ ULAS_ASMDIR_SETCHRCODE, ULAS_ASMDIR_CHR,
+ ULAS_ASMDIR_REP};
enum ulas_asmdir dir = ULAS_ASMDIR_NONE;
other_writes += ulas_asmdirchr(dst, &line, n, &rc);
break;
case ULAS_ASMDIR_REP:
+ rc = ulas_asmdirrep(dst, src, &line, n);
break;
case ULAS_ASMDIR_PAD:
// TODO: pad is the same as .fill n, $ - n