Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
8.5 KiB

  1. //debug();
  2. //
  3. // This program generates html documentation for script functions.
  4. // It merely converts comments with a certain syntax into documentation.
  5. // Example:
  6. //
  7. // /*gm
  8. // \lib Library Name
  9. // */
  10. //
  11. // /*gm
  12. // \function Function name
  13. // \brief Brief description of function
  14. // \param Parameter description, you should describe type information
  15. // \return Return value description
  16. // */
  17. //
  18. //
  19. // \function CreateGMDocumenter
  20. //
  21. global CreateGMDocumenter = function()
  22. {
  23. documenter = table
  24. (
  25. // \function ExtractGmCommentStrings
  26. // \param fp is source file handle
  27. // \param commentHandler is a function taking 2 params, comment string and context
  28. // \param context is passed to comment handler
  29. ExtractCommentStrings = function(fp, commentHandler, context)
  30. {
  31. openGmComment = "/*gm";
  32. openGmCommentLen = openGmComment.Length();
  33. closeGmComment = "*/";
  34. closeGmCommentLen = closeGmComment.Length();
  35. line = fp.ReadLine();
  36. while(line)
  37. {
  38. pos = line.Find(openGmComment);
  39. while(pos >= 0)
  40. {
  41. pos = pos + openGmCommentLen;
  42. line = line.Right(line.Length() - pos);
  43. comment = "";
  44. // eat up lines untill end of comment
  45. pos = line.Find(closeGmComment);
  46. while(pos < 0)
  47. {
  48. comment = comment + line;
  49. line = fp.ReadLine();
  50. if(line == null)
  51. {
  52. pos = 0;
  53. }
  54. else
  55. {
  56. pos = line.Find(closeGmComment);
  57. }
  58. }
  59. if(line)
  60. {
  61. comment = comment + line.Left(pos);
  62. line = line.Right(line.Length() - (pos + closeGmCommentLen));
  63. pos = line.Find(openGmComment);
  64. }
  65. else
  66. {
  67. pos = -1;
  68. }
  69. if(comment.Length() > 0)
  70. {
  71. // process comment string
  72. comment = comment.ReplaceCharsInSet(' ', "\r\n\v");
  73. commentHandler(comment, context);
  74. }
  75. }
  76. line = fp.ReadLine();
  77. }
  78. },
  79. // \function CommentHandler
  80. // \param comment is an incoming comment string
  81. // \param context is a table with a m_sections table where each m_section
  82. // is a function taking the section string and the context
  83. // context also has a BeginComment() call
  84. CommentHandler = function(comment, context)
  85. {
  86. if(comment and comment.Length())
  87. {
  88. commentSet = table();
  89. foreach(section and sectionHandler in context.m_sections)
  90. {
  91. search = comment;
  92. sectionStart = search.Find(section);
  93. sectionLength = section.Length();
  94. offset = 0;
  95. while(sectionStart >= 0)
  96. {
  97. commentSet[offset + sectionStart] = section;
  98. offset = offset + sectionLength;
  99. search = search.Right(search.Length() - sectionLength);
  100. sectionStart = search.Find(section);
  101. }
  102. }
  103. // commentSet is now a table containing the start positions of each comment bit.
  104. length = comment.Length();
  105. local j;
  106. for(i = 0; i < length; i = i + 1)
  107. {
  108. if(commentSet[i])
  109. {
  110. // find the next comment...
  111. for(j = i + 1; j < length; j = j + 1)
  112. {
  113. if(commentSet[j] or j == (length - 1))
  114. {
  115. section = commentSet[i];
  116. sectionLength = section.Length();
  117. first = i + sectionLength;
  118. count = (j - i) - sectionLength;
  119. subComment = comment.Mid(first, count);
  120. context.m_sections[section](subComment, context);
  121. break;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. },
  128. m_files = table(),
  129. // \function AddFile will add a file to be documented
  130. AddFile = function(filename)
  131. {
  132. .m_files[tableCount(.m_files)] = filename;
  133. },
  134. // \function CreateDocumentation will create documentation for all added files
  135. // \param path is the output path for the resulting .html docco
  136. CreateDocumentation = function(filename)
  137. {
  138. context = table();
  139. context.m_sections = table();
  140. context.m_htmlOut = system.File();
  141. context.m_xmlOut = system.File();
  142. context.m_lib = "";
  143. context.m_sections[`\lib`] = function(comment, context)
  144. {
  145. comment = comment.TrimLeft().TrimRight();
  146. // trim parenthesis
  147. context.Write("<BR><HR>\n");
  148. context.Heading(1, comment);
  149. context.Write("<HR><BR>\n");
  150. context.m_lib = comment;
  151. };
  152. context.m_sections[`\function`] = function(comment, context)
  153. {
  154. comment = comment.TrimLeft().TrimRight();
  155. // trim parenthesis
  156. context.Write("<HR>\n");
  157. context.Write(format(`<a name="%s::%s">`,context.m_lib,comment));
  158. context.Heading(3, comment);
  159. context.Write(`</a>`);
  160. context.XMLWrite(format(`<function name="%s::%s"/>`, context.m_lib, comment));
  161. };
  162. context.m_sections[`\brief`] = function(comment, context)
  163. {
  164. context.Write(format("<B><EM>Brief:</B></EM>%s<BR>", comment));
  165. };
  166. context.m_sections[`\param`] = function(comment, context)
  167. {
  168. context.Write(format("<B><EM>Param:</B></EM>%s<BR>", comment));
  169. };
  170. context.m_sections[`\return`] = function(comment, context)
  171. {
  172. context.Write(format("<B><EM>Return:</B></EM>%s<BR>", comment));
  173. };
  174. context.m_sections[`\sa`] = function(comment, context)
  175. {
  176. context.Write(format("<B><EM>See Also:</B></EM>%s<BR>", comment));
  177. };
  178. context.Heading = function(number, string)
  179. {
  180. .m_htmlOut.WriteString(format("<H%d>%s</H%d>\n", number, string, number));
  181. };
  182. context.m_sections[`\this`] = function(comment, context)
  183. {
  184. context.Write(format("<B><EM>This:</B></EM>%s<BR>", comment));
  185. };
  186. context.Paragraph = function(string)
  187. {
  188. .m_htmlOut.WriteString(format("<P>%s</P>\n", string));
  189. };
  190. context.Write = function(string)
  191. {
  192. .m_htmlOut.WriteString(string);
  193. };
  194. context.XMLWrite = function(string)
  195. {
  196. if(.m_xmlOut)
  197. {
  198. .m_xmlOut.WriteString(string);
  199. }
  200. };
  201. xmlFilename = filename.SetExtension("xml");
  202. if(!context.m_xmlOut.Open(xmlFilename, 0))
  203. {
  204. print("** ERROR: Failed to open XML output file '",xmlFilename,"' ! **");
  205. context.m_xmlOut = null;
  206. }
  207. context.XMLWrite(`<?xml version="1.0" encoding="utf-8"?>`);
  208. context.XMLWrite("<functions>");
  209. //
  210. if(context.m_htmlOut.Open(filename, 0))
  211. {
  212. // write html head
  213. context.Write("<HTML><HEAD><TITLE>GM Documentation</TITLE></HEAD><BODY>");
  214. foreach(file in .m_files)
  215. {
  216. fp = system.File();
  217. if(fp.Open(file))
  218. {
  219. print(`Documenting`, file, `...`);
  220. .ExtractCommentStrings(fp,.CommentHandler,context);
  221. fp.Close();
  222. }
  223. }
  224. context.XMLWrite("</functions>");
  225. if(context.m_xmlOut)
  226. {
  227. context.m_xmlOut.Close();
  228. }
  229. context.Write("</BODY></HTML>");
  230. context.m_htmlOut.Close();
  231. }
  232. }
  233. );
  234. return documenter;
  235. };
  236. /*
  237. *
  238. * Entry Point
  239. *
  240. */
  241. print("Starting GMDoc...");
  242. inFile = arg[0]; // directory/file listings of 'to be documented' files
  243. outFile = arg[1]; // ouput help files
  244. documenter = CreateGMDocumenter();
  245. dirsFile = system.File();
  246. if(!dirsFile.Open(inFile, 1))
  247. {
  248. print("** Failed to open input file! **");
  249. }
  250. else
  251. {
  252. nextLine = dirsFile.ReadLine();
  253. while(nextLine)
  254. {
  255. nextLine = nextLine.TrimRight(); // carriage return syndrome
  256. path = nextLine;
  257. filename = nextLine.GetFilename();
  258. pos = filename.Find(".cpp",filename.Length() - 5);
  259. if(pos >= 0) // doc file
  260. {
  261. if(system.FileExists(path))
  262. {
  263. documenter.AddFile(path);
  264. }
  265. }
  266. else // doc directory
  267. {
  268. handle = system.FileFindFirst(path ^ `\*.*`);
  269. while(handle)
  270. {
  271. extension = handle.filename.GetExtension().Lower();
  272. print(extension);
  273. if(extension == `cpp` or extension == `gm`)
  274. {
  275. if(system.FileExists(path ^ handle.filename))
  276. {
  277. documenter.AddFile(path ^ handle.filename);
  278. }
  279. }
  280. handle = system.FileFindNext(handle);
  281. }
  282. }
  283. nextLine = dirsFile.ReadLine(); // read next line
  284. }
  285. }
  286. dirsFile.Close();
  287. documenter.CreateDocumentation(outFile);
  288. print(`Done.`);