generate-logging-defs.tcl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. #!/usr/bin/tclsh
  2. #*
  3. #* SRT - Secure, Reliable, Transport
  4. #* Copyright (c) 2020 Haivision Systems Inc.
  5. #*
  6. #* This Source Code Form is subject to the terms of the Mozilla Public
  7. #* License, v. 2.0. If a copy of the MPL was not distributed with this
  8. #* file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #*
  10. #*/
  11. #
  12. #*****************************************************************************
  13. #written by
  14. # Haivision Systems Inc.
  15. #*****************************************************************************
  16. # What fields are there in every entry
  17. set model {
  18. longname
  19. shortname
  20. id
  21. description
  22. }
  23. # Logger definitions.
  24. # Comments here allowed, just only for the whole line.
  25. # Use values greater than 0. Value 0 is reserved for LOGFA_GENERAL,
  26. # which is considered always enabled.
  27. set loggers {
  28. GENERAL gg 0 "General uncategorized log, for serious issues only"
  29. SOCKMGMT sm 1 "Socket create/open/close/configure activities"
  30. CONN cn 2 "Connection establishment and handshake"
  31. XTIMER xt 3 "The checkTimer and around activities"
  32. TSBPD ts 4 "The TsBPD thread"
  33. RSRC rs 5 "System resource allocation and management"
  34. CONGEST cc 7 "Congestion control module"
  35. PFILTER pf 8 "Packet filter module"
  36. API_CTRL ac 11 "API part for socket and library managmenet"
  37. QUE_CTRL qc 13 "Queue control activities"
  38. EPOLL_UPD ei 16 "EPoll, internal update activities"
  39. API_RECV ar 21 "API part for receiving"
  40. BUF_RECV br 22 "Buffer, receiving side"
  41. QUE_RECV qr 23 "Queue, receiving side"
  42. CHN_RECV kr 24 "CChannel, receiving side"
  43. GRP_RECV gr 25 "Group, receiving side"
  44. API_SEND as 31 "API part for sending"
  45. BUF_SEND bs 32 "Buffer, sending side"
  46. QUE_SEND qs 33 "Queue, sending side"
  47. CHN_SEND ks 34 "CChannel, sending side"
  48. GRP_SEND gs 35 "Group, sending side"
  49. INTERNAL in 41 "Internal activities not connected directly to a socket"
  50. QUE_MGMT qm 43 "Queue, management part"
  51. CHN_MGMT km 44 "CChannel, management part"
  52. GRP_MGMT gm 45 "Group, management part"
  53. EPOLL_API ea 46 "EPoll, API part"
  54. }
  55. set hidden_loggers {
  56. # Haicrypt logging - usually off.
  57. HAICRYPT hc 6 "Haicrypt module area"
  58. # defined in apps, this is only a stub to lock the value
  59. APPLOG ap 10 "Applications"
  60. }
  61. set globalheader {
  62. /*
  63. WARNING: Generated from ../scripts/generate-logging-defs.tcl
  64. DO NOT MODIFY.
  65. Copyright applies as per the generator script.
  66. */
  67. }
  68. # This defines, what kind of definition will be generated
  69. # for a given file out of the log FA entry list.
  70. # Fields:
  71. # - prefix/postfix model
  72. # - logger_format
  73. # - hidden_logger_format
  74. # COMMENTS NOT ALLOWED HERE! Only as C++ comments inside C++ model code.
  75. set special {
  76. srtcore/logger_default.cpp {
  77. if {"$longname" == "HAICRYPT"} {
  78. puts $od "
  79. #if ENABLE_HAICRYPT_LOGGING
  80. allfa.set(SRT_LOGFA_HAICRYPT, true);
  81. #endif"
  82. }
  83. }
  84. }
  85. proc GenerateModelForSrtH {} {
  86. # `path` will be set to the git top path
  87. global path
  88. set fd [open [file join $path srtcore/srt.h] r]
  89. set contents ""
  90. set state read
  91. set pass looking
  92. while { [gets $fd line] != -1 } {
  93. if { $state == "read" } {
  94. if { $pass != "passed" } {
  95. set re [regexp {SRT_LOGFA BEGIN GENERATED SECTION} $line]
  96. if {$re} {
  97. set state skip
  98. set pass found
  99. }
  100. }
  101. append contents "$line\n"
  102. continue
  103. }
  104. if {$state == "skip"} {
  105. if { [string trim $line] == "" } {
  106. # Empty line, continue skipping
  107. continue
  108. }
  109. set re [regexp {SRT_LOGFA END GENERATED SECTION} $line]
  110. if {!$re} {
  111. # Still SRT_LOGFA definitions
  112. continue
  113. }
  114. # End of generated section. Switch back to pass-thru.
  115. # First fill the gap
  116. append contents "\n\$entries\n\n"
  117. append contents "$line\n"
  118. set state read
  119. set pass passed
  120. }
  121. }
  122. close $fd
  123. # Sanity check
  124. if {$pass != "passed"} {
  125. error "Invalid contents of `srt.h` file, can't find '#define SRT_LOGFA_' phrase"
  126. }
  127. return $contents
  128. }
  129. # COMMENTS NOT ALLOWED HERE! Only as C++ comments inside C++ model code.
  130. # (NOTE: Tcl syntax highlighter will likely falsely highlight # as comment here)
  131. #
  132. # Model: TARGET-NAME { format-model logger-pattern hidden-logger-pattern }
  133. #
  134. # Special syntax:
  135. #
  136. # %<command> : a high-level command execution. This declares a command that
  137. # must be executed to GENERATE the model. Then, [subst] is executed
  138. # on the results.
  139. #
  140. # = : when placed as the hidden-logger-pattern, it's equal to logger-pattern.
  141. #
  142. set generation {
  143. srtcore/srt.h {
  144. {%GenerateModelForSrtH}
  145. {#define [format "%-20s %-3d" SRT_LOGFA_${longname} $id] // ${shortname}log: $description}
  146. =
  147. }
  148. srtcore/logger_default.cpp {
  149. {
  150. $globalheader
  151. #include "srt.h"
  152. #include "logging.h"
  153. #include "logger_defs.h"
  154. namespace srt_logging
  155. {
  156. AllFaOn::AllFaOn()
  157. {
  158. $entries
  159. }
  160. } // namespace srt_logging
  161. }
  162. {
  163. allfa.set(SRT_LOGFA_${longname}, true);
  164. }
  165. }
  166. srtcore/logger_defs.cpp {
  167. {
  168. $globalheader
  169. #include "srt.h"
  170. #include "logging.h"
  171. #include "logger_defs.h"
  172. namespace srt_logging { AllFaOn logger_fa_all; }
  173. // We need it outside the namespace to preserve the global name.
  174. // It's a part of "hidden API" (used by applications)
  175. SRT_API srt_logging::LogConfig srt_logger_config(srt_logging::logger_fa_all.allfa);
  176. namespace srt_logging
  177. {
  178. $entries
  179. } // namespace srt_logging
  180. }
  181. {
  182. Logger ${shortname}log(SRT_LOGFA_${longname}, srt_logger_config, "SRT.${shortname}");
  183. }
  184. }
  185. srtcore/logger_defs.h {
  186. {
  187. $globalheader
  188. #ifndef INC_SRT_LOGGER_DEFS_H
  189. #define INC_SRT_LOGGER_DEFS_H
  190. #include "srt.h"
  191. #include "logging.h"
  192. namespace srt_logging
  193. {
  194. struct AllFaOn
  195. {
  196. LogConfig::fa_bitset_t allfa;
  197. AllFaOn();
  198. };
  199. $entries
  200. } // namespace srt_logging
  201. #endif
  202. }
  203. {
  204. extern Logger ${shortname}log;
  205. }
  206. }
  207. apps/logsupport_appdefs.cpp {
  208. {
  209. $globalheader
  210. #include "logsupport.hpp"
  211. LogFANames::LogFANames()
  212. {
  213. $entries
  214. }
  215. }
  216. {
  217. Install("$longname", SRT_LOGFA_${longname});
  218. }
  219. {
  220. Install("$longname", SRT_LOGFA_${longname});
  221. }
  222. }
  223. }
  224. # EXECUTION
  225. set here [file dirname [file normalize $argv0]]
  226. if {[lindex [file split $here] end] != "scripts"} {
  227. puts stderr "The script is in weird location."
  228. exit 1
  229. }
  230. set path [file join {*}[lrange [file split $here] 0 end-1]]
  231. # Utility. Allows to put line-oriented comments and have empty lines
  232. proc no_comments {input} {
  233. set output ""
  234. foreach line [split $input \n] {
  235. set nn [string trim $line]
  236. if { $nn == "" || [string index $nn 0] == "#" } {
  237. continue
  238. }
  239. append output $line\n
  240. }
  241. return $output
  242. }
  243. proc generate_file {od target} {
  244. global globalheader
  245. lassign [dict get $::generation $target] format_model pattern hpattern
  246. set ptabprefix ""
  247. if {[string index $format_model 0] == "%"} {
  248. set command [string range $format_model 1 end]
  249. set format_model [eval $command]
  250. }
  251. if {$format_model != ""} {
  252. set beginindex 0
  253. while { [string index $format_model $beginindex] == "\n" } {
  254. incr beginindex
  255. }
  256. set endindex $beginindex
  257. while { [string is space [string index $format_model $endindex]] } {
  258. incr endindex
  259. }
  260. set tabprefix [string range $pattern $beginindex $endindex-1]
  261. set newformat ""
  262. foreach line [split $format_model \n] {
  263. if {[string trim $line] == ""} {
  264. append newformat "\n"
  265. continue
  266. }
  267. if {[string first $tabprefix $line] == 0} {
  268. set line [string range $line [string length $tabprefix] end]
  269. }
  270. append newformat $line\n
  271. set ie [string first {$} $line]
  272. if {$ie != -1} {
  273. if {[string range $line $ie end] == {$entries}} {
  274. set ptabprefix "[string range $line 0 $ie-1]"
  275. }
  276. }
  277. }
  278. set format_model $newformat
  279. unset newformat
  280. }
  281. set entries ""
  282. if {[string trim $pattern] != "" } {
  283. set prevval 0
  284. set pattern [string trim $pattern]
  285. # The first "$::model" will expand into variable names
  286. # as defined there.
  287. foreach [list {*}$::model] [no_comments $::loggers] {
  288. if {$prevval + 1 != $id} {
  289. append entries "\n"
  290. }
  291. append entries "${ptabprefix}[subst -nobackslashes $pattern]\n"
  292. set prevval $id
  293. }
  294. }
  295. if {$hpattern != ""} {
  296. if {$hpattern == "="} {
  297. set hpattern $pattern
  298. } else {
  299. set hpattern [string trim $hpattern]
  300. }
  301. # Extra line to separate from the normal entries
  302. append entries "\n"
  303. foreach [list {*}$::model] [no_comments $::hidden_loggers] {
  304. append entries "${ptabprefix}[subst -nobackslashes $hpattern]\n"
  305. }
  306. }
  307. if { [dict exists $::special $target] } {
  308. set code [subst [dict get $::special $target]]
  309. # The code should contain "append entries" !
  310. eval $code
  311. }
  312. set entries [string trim $entries]
  313. if {$format_model == ""} {
  314. set format_model $entries
  315. }
  316. # For any case, cut external spaces
  317. puts $od [string trim [subst -nocommands -nobackslashes $format_model]]
  318. }
  319. proc debug_vars {list} {
  320. set output ""
  321. foreach name $list {
  322. upvar $name _${name}
  323. lappend output "${name}=[set _${name}]"
  324. }
  325. return $output
  326. }
  327. # MAIN
  328. set entryfiles $argv
  329. if {$entryfiles == ""} {
  330. set entryfiles [dict keys $generation]
  331. } else {
  332. foreach ef $entryfiles {
  333. if { $ef ni [dict keys $generation] } {
  334. error "Unknown generation target: $entryfiles"
  335. }
  336. }
  337. }
  338. foreach f $entryfiles {
  339. # Set simple relative path, if the file isn't defined as path.
  340. if { [llength [file split $f]] == 1 } {
  341. set filepath $f
  342. } else {
  343. set filepath [file join $path $f]
  344. }
  345. puts stderr "Generating '$filepath'"
  346. set od [open $filepath.tmp w]
  347. generate_file $od $f
  348. close $od
  349. if { [file exists $filepath] } {
  350. puts "WARNING: will overwrite exiting '$f'. Hit ENTER to confirm, or Control-C to stop"
  351. gets stdin
  352. }
  353. file rename -force $filepath.tmp $filepath
  354. }
  355. puts stderr Done.