use b_plain use cz/vars number_lines(cstr src_file) # FIXME do not put line numbers in macros or anything that ends up # in a .bh file... # but probably should do something when including such a file # hmm actually macro expansions should all report a single caller line number # for all lines of the expansion.. and possibly the line in the macro source # too, etc for nested macro expansions. complex cstr filename_quoted = qq(src_file) int line_no = 1 for_vec(i, lines, cstr) cstr l = *i # TODO use a function to get this data about the line int tabs = 0 int spaces = 0 boolean blank = 1 boolean is_comment = 0 boolean has_comment = 0 # has_comment is bogus because not tokenized, no matter boolean has_labels = 0 char *after_tabs = l for_cstr(j, l) if !isspace(*j) if *j == '#' has_comment = 1 if blank is_comment = 1 blank = 0 eif *j == '\t' if !has_comment ++tabs after_tabs = j+1 if !blank has_labels = 1 eif !spaces && blank while *j == ' ' ++spaces ; ++j --j if tabs > 0 && spaces == 0 && !blank && !is_comment if has_labels int len = after_tabs-l cstr o = tofree(Malloc(len+2)) strncpy(o, l, len) o[len] = '.' o[len+1] = '\0' vec_push(work, o) new(b, buffer, line_initial_space) buffer_cat_chars(b, '\t', tabs) Sprintf(b, "^line %d %s", line_no, filename_quoted) vec_push(work, tofree(buffer_to_cstr(b))) buffer_cat_chars(b, '\t', tabs) new(b1, buffer, line_initial_space) buffer_cat_chars(b1, '\t', tabs) buffer_cat_cstr(b1, after_tabs) vec_push(work, tofree(buffer_to_cstr(b1))) else new(b, buffer, line_initial_space) buffer_cat_chars(b, '\t', tabs) Sprintf(b, "^line %d %s", line_no, filename_quoted) vec_push(work, tofree(buffer_to_cstr(b))) vec_push(work, l) else vec_push(work, l) ++line_no swap(lines, work) vecclr(work)