mata mata set matastrict on real scalar sp_nbrace(string scalar str, string scalar type) { real scalar pos, n pos = 1 n = 0 while( (pos = ustrpos(str,type, pos) + 1) != 1 ) { n = n + 1 } return(n) } string scalar sp_stripbraces(string scalar str) { real scalar start , finish if (usubstr(ustrltrim(str), 1,1) == "{" & usubstr(ustrrtrim(str),-1,1) == "}") { start = ustrpos(str,"{") finish = ustrrpos(str, "}") return(usubstr(str,start+1, finish-start-1)) } else { return(str) } } string scalar sp_stripbrackets(string scalar str) { real scalar start , finish if (usubstr(ustrltrim(str), 1,1) == "[" & usubstr(ustrrtrim(str),-1,1) == "]") { start = ustrpos(str,"[") finish = ustrrpos(str, "]") return(usubstr(str,start+1, finish-start-1)) } else { return(str) } } string scalar sp_remove_all_braces(string scalar str) { str = usubinstr(str, "{", "", .) str = usubinstr(str, "}", "", .) return(str) } void sp_parse_authors(struct strpres scalar pres) { real scalar i string rowvector key string matrix parsed for(i = 1 ; i <= rows(pres.bib.keys); i++) { key = pres.bib.keys[i] parsed = sp_parse_author(pres,key) key = (key,"author_first") asarray(pres.bib.bibdb,key, parsed[.,1]) key[2] = "author_last" asarray(pres.bib.bibdb,key, parsed[.,2]) } } string colvector sp_split_on_and(string scalar str) { string colvector res string scalar temp, token transmorphic scalar t res = J(0,1, "") temp = "" t = tokeninit(" ", "", "{}") tokenset(t, str) while ((token= tokenget(t)) != "") { if (token == "and" & temp != "") { res = res \ temp temp = "" } else { temp = temp + " " + token } } res = res \ temp return(res) } string rowvector sp_parse_name(string scalar str) { string scalar first, last string rowvector temp real scalar i, hascomma transmorphic scalar t first = "" last = "" hascomma = 0 t = tokeninit(" ", ",", "{}") tokenset(t, str) temp = tokengetall(t) for (i=1 ; i <= cols(temp); i++) { if (temp[i] == ",") { last = first first = "" hascomma = 1 } else { if (hascomma == 1) { first = first + " " + temp[i] } } if (hascomma == 0) { if (i == cols(temp)) { last = temp[i] } else { first = first + " " + temp[i] } } } last = sp_stripbraces(last) return((ustrtrim(first), ustrtrim(last))) } string matrix sp_parse_author(struct strpres scalar pres, string scalar key) { real scalar i string colvector unparsed string matrix parsed parsed = J(0,2,"") unparsed = asarray(pres.bib.bibdb,(key,"author")) if (unparsed != "") { unparsed = sp_split_on_and(unparsed) for (i = 1 ; i <= rows(unparsed) ; i++) { parsed = parsed \ sp_parse_name(unparsed[i]) } } return(parsed) } void sp_set_style(struct strpres scalar pres) { if (pres.bib.stylefile == "") { sp_base_style(pres) } else { sp_import_style(pres) } } void sp_base_style(struct strpres scalar pres) { string rowvector style style = ("{p 4 8 2}", "[author]", " (", "[year]", "), {it:", "[title]", "}. ", "[address]", ": ", "[publisher]", ".{p_end}") asarray(pres.bib.style, "book", style) style = ("{p 4 8 2}", "[author]", " (", "[year]", `"), ""', "[title]", `"", {it:"', "[journal]", "}, {bf:", "[volume]", "}(", "[number]", "), pp. ", "[pages]", ".{p_end}") asarray(pres.bib.style, "article", style) style = ("{p 4 8 2}", "[author]", " (", "[year]", `"), ""', "[title]", `"". In {it:"', "[booktitle]", "}, edited by ", "[editor]", ", pp. ", "[pages]", ". ", "[address]", ": ", "[publisher]", ".{p_end}") asarray(pres.bib.style, "incollection", style) style = ("{p 4 8 2}", "[author]", " (", "[year]", "), {it:", "[title]", "}. ", "[school]", ".{p_end}") asarray(pres.bib.style, "phdthesis", style) style = ("{p 4 8 2}", "[author]", " (", "[year]", "), {it:", "[title]", "}. ", "[note]", ".{p_end}") asarray(pres.bib.style, "unpublished", style) } void sp_import_style(struct strpres scalar pres) { real scalar in_entry, fh, openbraces, closebraces string scalar entry, line in_entry = 0 fh = sp_fopen(pres, pres.bib.stylefile, "r") while ((line = fget(fh)) != J(0,0,"") ) { if ( in_entry == 0 & usubstr(ustrltrim(line),1,1) == "@") { in_entry = 1 openbraces = 0 closebraces = 0 entry = "" } if (in_entry == 1) { openbraces = openbraces + sp_nbrace(line, "{") closebraces = closebraces + sp_nbrace(line, "}") entry = entry + line if (openbraces - closebraces == 0) { in_entry = 0 sp_parse_style_entry( pres, entry ) } } } sp_fclose(pres,fh) } void sp_parse_style_entry(struct strpres scalar pres, string scalar entry) { real scalar st, fi string scalar type string rowvector res transmorphic scalar t st = ustrpos(entry, "@") + 1 fi = ustrpos(entry, "{") type = usubstr(entry, st , fi - st) entry = ustrtrim(stripbraces(usubstr(entry, fi, .))) t = tokeninit("", (""), ("[]")) tokenset(t, entry) res = tokengetall(t) asarray(pres.bib.style, type, res) } void sp_write_bib(struct strpres scalar pres, real scalar fh) { real scalar i for (i = 1 ; i <= rows(pres.bib.refs) ; i++) { sp_write_bib_entry(pres, pres.bib.refs[i], fh) if (i < rows(pres.bib.refs)) fput(fh, " ") } } void sp_write_bib_entry(struct strpres scalar pres, string scalar key, real scalar fh) { string scalar type, res, entry string rowvector mask string colvector first, last real scalar i, j real colvector slides fput(fh, "{marker " + key + "}{...}") type = asarray(pres.bib.bibdb,(key,"type")) mask = asarray(pres.bib.style, type) res = "" for (i = 1; i<=cols(mask); i++) { if (usubstr(mask[i],1,1) == "[") { entry = sp_stripbrackets(mask[i]) if (entry == "author") { first = asarray(pres.bib.bibdb, (key, "author_first")) last = asarray(pres.bib.bibdb, (key, "author_last")) if (pres.bib.authorstyle == "first last") { for (j = 1; j < rows(first) ; j++) { res = res + first[j] + " " + last[j] if (rows(first)>2) res = res + "," if (j < rows(first)-1) res = res + " " } if (j > 1) res = res + " " + pres.bib.and + " " res = res + first[j] + " " + last[j] } else { for (j = 1; j < rows(first) ; j++) { res = res + last[j] + ", " + first[j] if (rows(first)>2) res = res + ";" if (j < rows(first)-1) res = res + " " } if (j > 1) res = res + " " + pres.bib.and + " " res = res + last[j] + ", " + first[j] } } else if (entry == "year") { res = res + asarray(pres.bib.bibdb,(key,"year")) + asarray(pres.bib.bibdb,(key,"postfix")) } else { res = res + asarray(pres.bib.bibdb,(key,entry)) } } else{ res = res + mask[i] } } fput(fh, res) } string scalar sp_write_single_ref(struct strpres scalar pres, string scalar key) { string matrix authors string scalar res real scalar i authors = asarray(pres.bib.bibdb, (key,"author_last")) res = "" for (i = 1 ; i < rows(authors); i++) { if (i > 1 & rows(authors) > 2) res = res + ", " res = res + authors[i] } if (i > 2) res = res + "," if (i > 1) res = res + " " + pres.bib.and + " " res = res + authors[i] res = res + " " + asarray(pres.bib.bibdb,(key,"year")) + asarray(pres.bib.bibdb,(key,"postfix")) return(res) } string scalar sp_write_ref(struct strpres scalar pres, string scalar str, real scalar snr) { transmorphic scalar t string scalar token, res, ref real scalar nrefs, ncomment nrefs = 0 ncomment = 0 res = "" t = tokeninit(" ", "", "{}" ) tokenset(t, str) while ( (token = tokenget(t)) != "") { if ( usubstr(token,1,1) != "{" ) { nrefs = nrefs + 1 if (nrefs > 1 & ncomment < 2) res = res + "; " ncomment = 0 ref = sp_write_single_ref(pres,token) ref = "{view slide" + strofreal(pres.bib.bibslide) + ".smcl##" + token + ":" + ref + "}" res = res + ref } else { ncomment = ncomment + 1 if (nrefs >= 1 & ncomment == 2) res = res + "; " res = res + sp_stripbraces(token) } } res = "(" + res + ")" return(res) } string scalar sp_replaceref(struct strpres scalar pres, string scalar line, real scalar snr) { real scalar st, fi string scalar rawref, ref st = 0 while( (st = ustrpos(line, "/*cite", st) + 1 ) != 1) { fi = ustrpos(line, "*/", st) rawref = usubstr(line,st+6, fi-st-6) ref = sp_write_ref(pres, rawref, snr) line = usubstr(line,1, st-2) + ref + usubstr(line,fi+2,.) } return(line) } void sp_read_bib(struct strpres scalar pres) { real scalar in_entry, fh, openbraces, closebraces string scalar line, entry in_entry = 0 fh = sp_fopen(pres, pres.bib.bibfile, "r") while ( (line = fget(fh)) != J(0,0,"") ) { line = sp_remove_tab(pres,line) if ( in_entry == 0 & usubstr(ustrltrim(line),1,1) == "@") { in_entry = 1 openbraces = 0 closebraces = 0 entry = "" } if (in_entry == 1) { openbraces = openbraces + sp_nbrace(line, "{") closebraces = closebraces + sp_nbrace(line, "}") entry = entry + line if (openbraces - closebraces == 0) { in_entry = 0 sp_parse_entry(entry, pres) } } } sp_fclose(pres,fh) sp_parse_authors(pres) } void sp_parse_entry(string scalar entry, struct strpres scalar pres) { string scalar key, type, content, token real scalar k transmorphic scalar t t = tokeninit(" "+char(9), (","), ("{}")) tokenset(t, entry) type = tokenget(t) type = strlower(tokens(type, "@")[2]) tokenset(t,sp_stripbraces(tokenget(t))) key = tokenget(t) pres.bib.keys = pres.bib.keys \ key asarray(pres.bib.bibdb,(key,"type"),type) while ((token= tokenget(t)) != "") { if (token == "," ) { k = -1 if (key != "" & content != "" ) { if (type == "author") { content = sp_stripbraces(content) } else { content = sp_remove_all_braces(content) } asarray(pres.bib.bibdb,(key,type), content) } } k = k +1 if (k == 1) { type = token } if (k == 2) { if (token != "=") { error(198) } } if (k == 3) { content = token } if (k >= 4) { content = content + " " + token } } if (key != "" & content != "" ) { if (type == "author") { content = sp_stripbraces(content) } else { content = sp_remove_all_braces(content) } asarray(pres.bib.bibdb,(key,type), content) } } string colvector sp_extract_rawrefs(string scalar line, real scalar lnr) { real scalar st, fi string colvector res string scalar err res = J(0,1, "") st = 0 while( (st = ustrpos(line, "/*cite", st) + 1 ) != 1) { fi = ustrpos(line, "*/", st) if (fi == 0) { err = "{err}a /*cite was started on line {res}" + strofreal(lnr) + " {err} but was not finished by a */" printf(err) exit(198) } res = res \ usubstr(line,st+6, fi-st-6) } return(res) } string colvector sp_extract_refs(string scalar line, real scalar lnr) { string colvector rawrefs, res string scalar token real scalar i transmorphic scalar t res = J(0,1, "") t = tokeninit(" ", "", "{}" ) rawrefs = sp_extract_rawrefs(line, lnr) for (i = 1 ; i <= rows(rawrefs) ; i++) { tokenset(t, rawrefs[i]) while ( (token = tokenget(t)) != "") { if ( usubstr(token,1,1) != "{" ) { res = res \ token } } } return(res) } void sp_collect_refs(struct strpres scalar pres) { real scalar source, lnr, txtopen, i string scalar line string rowvector tline string colvector refs lnr = 0 txtopen = 0 source = sp_fopen(pres,pres.settings.other.source, "r") while ((line=fget(source))!=J(0,0,"")) { lnr = lnr + 1 tline = tokens(line) if (cols(tline) > 0) { if (tline[1] == "/*txt") txtopen = 1 if (tline[1] == "//txt") txtopen = 1 if (tline[1] == "txt*/") txtopen = 0 if (txtopen == 1 & pres.bib.write == "cited") { if (anyof(tline, "/*cite")) { refs = sp_extract_refs(line, lnr) for(i = 1 ; i <= rows(refs); i++) { if (pres.bib.refs == J(0,1,"")) { pres.bib.refs = refs[i] } else if (!anyof(pres.bib.refs,refs[i])) { pres.bib.refs = pres.bib.refs \ refs[i] } } } } } } if (pres.bib.write == "all") { pres.bib.refs = asarray_keys(pres.bib.bibdb) } sp_fix_collisions(pres) sp_fclose(pres,source) } void sp_collect_bib(struct strpres scalar pres) { real scalar source, dest, bibopen, bibslide real scalar txtopen, lnr string scalar err, line string rowvector tline bibopen = 0 bibslide = 0 lnr = 0 txtopen = 0 source = sp_fopen(pres,pres.settings.other.source, "r") dest = sp_fopen(pres,pres.bib.bibfile, "w") while ((line=fget(source))!=J(0,0,"")) { lnr = lnr + 1 tline = tokens(line) if (cols(tline) > 0) { if (tline[1] == "/*txt") txtopen = 1 if (tline[1] == "//txt") txtopen = 1 if (tline[1] == "txt*/") txtopen = 0 if (tline[1] == "bib*/") { if (bibopen == 0) { err = "{err}tried to close a bibliography on line {res}" + strofreal(lnr) + " {err}while none was open" printf(err) exit(198) } bibopen = 0 } if (tline[1] == "/*bib") { if (bibopen == 1) { err = "{err}tried to open bibliography on line {res}" + strofreal(lnr) + " {err}while one was already open" printf(err) exit(198) } if (bibslide == 0) { err = "{err}tried to open a bibliography on line {res}" + strofreal(lnr) + " {err}while not on a bibliography slide" printf(err) exit(198) } if (txtopen == 1) { err = "{err}tried to open a bibliography on line {res}" + strofreal(lnr) + " {err}while a textblock was open" printf(err) exit(198) } bibopen = 1 } else if (bibopen == 1) { fput(dest, line) } if (tline[1] == "//bib") { bibslide = 1 } if (tline[1] == "//endbib") { bibslide = 0 if (bibopen == 1) { err = "{err}tried to close the bibliography slide on " + "line {res}" + strofreal(lnr) + " {err}while a " + "bibliography was still open" printf(err) exit(198) } } } } sp_fclose(pres,source) sp_fclose(pres,dest) } void sp_fix_collisions(struct strpres scalar pres) { string matrix content string scalar key, pf real scalar i, k, dup real colvector o k = rows(pres.bib.refs) if (k > 1) { content = J(k,4, "") for (i = 1 ; i <= k; i++) { key = pres.bib.refs[i] if (asarray_contains(pres.bib.bibdb, (key,"author"))) { content[i,1] = invtokens(asarray(pres.bib.bibdb,(key, "author_last"))') content[i,2] = asarray(pres.bib.bibdb,(key, "year")) content[i,3] = asarray(pres.bib.bibdb,(key, "title")) content[i,4] = key } } o = order(content,(1,2,3,4)) content = content[o,.] pres.bib.refs = pres.bib.refs[o] dup = 0 for (i = 2 ; i <= k; i++) { if ( content[|i,1 \ i, 2|] == content[|i-1,1 \ i-1, 2|] ) { dup = dup + 1 if (dup == 1) { key = content[i-1,4] asarray(pres.bib.bibdb,(key, "postfix"), "a") } key = content[i,4] pf = strlower(numtobase26(dup+1)) asarray(pres.bib.bibdb,(key,"postfix"),pf) } else { dup = 0 } } } } void sp_init_bib(struct strpres scalar pres) { if (pres.bib.bibslide != .) { if (pres.bib.bibfile == "" ) { pres.bib.bibfile = st_tempfilename() sp_collect_bib(pres) } sp_read_bib(pres) sp_set_style(pres) sp_collect_refs(pres) } } end