const SRCS = [ 'xml/xml_api.cc', 'user/user_api.cc', 'user/user_init.c', 'user/user_vfs.cc', 'thread/thread_task.cc', 'thread/thread_pool.cc', 'render/render_context.c', 'render/render_gl2.c', 'render/render_gl3.c', 'render/render_util.c', 'engine/engine_derivative.c', 'engine/engine_io.c', 'engine/engine_sensor.c', 'engine/engine_callback.c', 'engine/engine_collision_driver.c', 'engine/engine_core_constraint.c', 'engine/engine_core_smooth.c', 'engine/engine_derivative_fd.c', 'engine/engine_forward.c', 'engine/engine_inverse.c', 'engine/engine_island.c', 'engine/engine_name.c', 'engine/engine_passive.c', 'engine/engine_plugin.cc', 'engine/engine_print.c', 'engine/engine_ray.c', 'engine/engine_setconst.c', 'engine/engine_solver.c', 'engine/engine_support.c', 'engine/engine_util_blas.c', 'engine/engine_util_container.c', 'engine/engine_util_errmem.c', 'engine/engine_util_misc.c', 'engine/engine_util_solve.c', 'engine/engine_util_spatial.c', 'engine/engine_util_sparse.c', 'engine/engine_vis_init.c', 'engine/engine_vis_interact.c', 'engine/engine_vis_state.c', 'engine/engine_vis_visualize.c', 'ui/ui_main.c', ]; class LineNumbers { constructor() { this.map = new Map(); } static fetch(src) { const url = `https://raw.githubusercontent.com/google-deepmind/mujoco/refs/heads/main/src/${src}`; const request = new XMLHttpRequest(); return new Promise((resolve, reject) => { request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { resolve(request.responseText); } else { reject(request.status); } } }; request.open('GET', url, true); request.send(); }); } fetchAll() { let requests = []; for (const src of SRCS) { requests.push(LineNumbers.fetch(src).then(contents => { this.processSrc(src, contents); }, reason => {/* swallow error */})); } Promise.all(requests).then(() => { const anchors = document.querySelectorAll('h3 a.reference.external'); for (const anchor of anchors) { const url = anchor.getAttribute('href'); if (url.startsWith('#')) { const key = url.substring(1); if (this.map.has(key)) { anchor.href = this.map.get(key); } else { console.log(`No line number found for ${key}`); } } } }); } processSrc(src, contents) { const lines = contents.split('\n'); const re = /^(const )?[a-zA-Z0-9_*]+\s(.+)\(.+[{,]$/; for (let i = 0; i < lines.length; i++) { if (lines[i].match(re)) { const key = lines[i].match(re)[2]; this.map.set(key, `https://github.com/google-deepmind/mujoco/blob/main/src/${src}#L${i+1}`); } } // edge cases if (src == 'user/user_api.cc') { for (let i = 0; i < lines.length; i++) { if (lines[i].startsWith('[[nodiscard]] int mj_recompile(')) { const key = 'mj_recompile'; this.map.set(key, `https://github.com/google-deepmind/mujoco/blob/main/src/${src}#L${i+1}`); } } } else if (src == 'engine/engine_io.c') { for (let i = 0; i < lines.length; i++) { if (lines[i].startsWith('void mj_freeStack(')) { const key = 'mj_freeStack'; this.map.set(key, `https://github.com/google-deepmind/mujoco/blob/main/src/${src}#L${i+1}`); } else if (lines[i].startsWith('void mj_markStack(')) { const key = 'mj_markStack'; this.map.set(key, `https://github.com/google-deepmind/mujoco/blob/main/src/${src}#L${i+1}`); } } } } } window.onload = () => { if (document.getElementById('fetchlines')) { let lines = new LineNumbers(); lines.fetchAll(); } };