Skip to content

Instantly share code, notes, and snippets.

@cybrox
Created March 3, 2015 22:16
Show Gist options
  • Save cybrox/b5dbb5ce6cea44b0651d to your computer and use it in GitHub Desktop.
Save cybrox/b5dbb5ce6cea44b0651d to your computer and use it in GitHub Desktop.
C Documentation Generator in Javascript
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
/**
* Javascript based C-Auto documentation generator
*
* This script generates an array with documentary information about every function
* present in the given input file. The output can be processed via lambda.
*
* Known Bugs:
* - You may not use untyped param descriptions as of now.
*/
var cdoc = {
functions: [], /* Array with all function information */
functiona: [], /* Array of arguments of the active function */
lines: 0, /* Number of total lines in the given file */
lengs: 0, /* Current parsing line in the given file */
index: 0, /* Index of the currently active function */
inFun: false, /* Indicator if we're in a function desc */
settings: { /* Default settings array */
typedParameters: false /* Parameter descriptions contain type */
},
/** \brief Auto-Document the given C file.
* This assumes, that the script has access to the file, which means that we
* need to either enable local file access or run this on a webserver.
*
* \param filepath The path to the respective C file
* \param callback The lambda to execute after generating the docs
*/
documentFile: function(filepath, callback){
$.get(filepath, function(payload){
cdoc.lines = payload.split("\n");
cdoc.lengs = cdoc.lines.length;
while (--cdoc.lengs > 0) {
var line = cdoc.lines[cdoc.lengs];
var type = 'unknown';
// Check if the line contains a function definition. */
if(name = line.match(/^[ ]*(static )?[A-z0-9_*]{3,} ([A-z0-9_]{5,})[ ]?\(/g)) {
var parts = name.split(' ');
var indez = (parts[0] == "static") ? 3 : 2;
var parms = line.match(/\(.*\)/);
var parmx = []; // buffer
cdoc.index = cdoc.addFunction(parts[--indez].replace("(", "").trim());
cdoc.addReturn(cdoc.index, parts[--indez], "");
// Temp store function arguments
if (parms != undefined && parms != null) {
cdoc.functiona = [];
parms[0].replace(/(\(|\))/, "").split(" ").forEach(function(x){
if (x.length > 3 && x != "const") parmx.push(x);
});
parmx.forEach(function(x, i){
if (i % 2 == 0) {
if (parmx[i+1] != undefined) {
if (parmx[i+1][0] == "*") x = "*"+x;
}
cdoc.functiona.push(x);
}
});
}
cdoc.inFun = true;
type = 'function';
}
// Check if the line contains a return definition */
if(match = line.match(/[ ]+(@|\\)return [A-z0-9_*]+/g)) {
var desc = line.replace(match[0], "").replace(/(\/|\*)+/, "").trim();
var type = match[0].replace(/(@|\/\/)return/, "").trim();
cdoc.addReturn(cdoc.index, type, desc);
type = 'return';
}
// Check if the line contains a param definition
if(match = line.match(/(@|\\)param [A-z0-9_*]+ [A-z0-9_]+/g)) {
var texts = line.replace(match[0], "").replace(/(\/|\*)+/, "").trim();
var parts = match[0].replace(/(\/|\*)/, "").trim();
parts = parts.split(' ');
cdoc.addParam(cdoc.index, parts[1], parts[2], texts);
type = 'param';
}
// Check if the line contains a brief description
if (match = line.match(/(@|\\)brief /g)) {
var brief = line.replace(match[0], "").replace(/(\/|\*)+/, "").trim();
cdoc.addProperty(cdoc.index, "brief", brief);
type = 'brief';
}
// Check if the line contains a date description
if (match = line.match(/(@|\\)date /g)) {
var date = line.replace(match[0], "").replace(/(\/|\*)+/, "").trim();
cdoc.addProperty(cdoc.index, "date", date);
type = 'date';
}
// Check if the line contains a author description
if (match = line.match(/(@|\\)author /g)) {
var author = line.replace(match[0], "").replace(/(\/|\*)+/, "").trim();
cdoc.addProperty(cdoc.index, "author", author);
type = 'author';
}
// Check if the line contains a bug description
if (match = line.match(/(@|\\)bug /g)) {
var bug = line.replace(match[0], "").replace(/(\/|\*)+/, "").trim();
cdoc.addBug(cdoc.index, bug);
type = 'bug';
}
// Check for a simple comment line
if (match = line.match(/[ ]*(\*|\/\/)[ ]*[^@\n\\]+$/g)) {
if (type != 'function') {
var desc = line.replace(/(\/|\*)+/, "").trim();
if (desc.length > 3) cdoc.addDescription(cdoc.index, desc);
type = 'comment';
}
}
// Check if we hit the end of a description block
if (line.match(/(\/\*\*|\/\/\/)/g)) {
cdoc.inFun = false;
type = 'blockend';
}
}
//call lambda
callback();
});
},
/** \brief Add a function to the functions index
* This will add a function object to the existing functions index in order
* to generate a hashmap with all available functions.
*
* \param name The name of the respective function
*/
addFunction: function (name) {
var existing = -1;
cdoc.functions.forEach(function(fun, i){
if(fun.name == name) existing = i;
});
if(existing != -1) return existing;
cdoc.functions.push({
name: name,
brief: "",
desc: "",
note: "",
bugs: [],
params: [],
returns: {
type: "",
desc: ""
},
});
return (cdoc.functions.length - 1);
},
/** \brief Add a single property to the object
* \param index The index of said function
* \param key The key of said property
* \param val The future value of this property
*/
addProperty: function (index, key, val) {
if(!cdoc.inFun) return;
cdoc.functions[index][key] = val;
},
/** \brief Add a description to a function
* \param index The index of said function
* \param desc The description string
*/
addDescription: function (index, desc) {
if(!cdoc.inFun) return;
if (cdoc.functions[index].desc.length != 0) desc += '\n';
cdoc.functions[index].desc = desc + cdoc.functions[index].desc;
},
/** \brief Add a return value to a given function index
* \param type The type of the return value
* \param desc The description of the return value
*/
addReturn: function (index, type, desc) {
if(!cdoc.inFun) return;
cdoc.functions[index].returns.type = type;
cdoc.functions[index].returns.desc = desc;
},
/** \brief Add a param value to a given function index
* \param index The index of said function
* \param type The type of the param value
* \param name The name of the parameter value
* \param desc The description of the param value
*/
addParam: function (index, type, name, desc) {
if(!cdoc.inFun) return;
if(!cdoc.settings.typedParameters) {
desc = name + " " + desc;
name = type;
type = cdoc.functiona[cdoc.functiona.length - 1 - cdoc.functions[index].params.length];
}
cdoc.functions[index].params.unshift({
type: type,
name: name,
desc: desc
});
},
/** \brief Add a bug to a given function
* \param index The index of said function
* \param bug The bug string
*/
addBug: function (index, bug) {
cdoc.functions[index].bugs.unshift(bug);
}
}
cdoc.documentFile('test.c', function(){
document.write(JSON.stringify(cdoc.functions));
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment