FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
daScript/daslib/env_registry.das at master · feiyunwill/daScript · GitHub
feiyunwill
/
daScript
Public
forked from
GaijinEntertainment/daScript
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
daScript
/
daslib
/
env_registry.das
Copy path
More file actions
More file actions
Latest commit
History
History
History
280 lines (253 loc) · 9.56 KB
Breadcrumbs
daScript
/
daslib
/
env_registry.das
Copy path
File metadata and controls
280 lines (253 loc) · 9.56 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
options
gen2
//! Shared scaffolding for a module's environment-knob registry. A registry module declares its
//! knobs as `[EnvConfig]` structs (daslib/clargs) and loads them once into `g_env_*` globals;
//! this module carries everything around that declaration that is the same for every adopter:
//! the ENVIRONMENT.md renderers, the enforcement-test scanners, and the sanctioned dynamic-name
//! readers. Worked examples: `dasllama/dasllama_env.das`, `llvm/daslib/llvm_env.das`.
module
env_registry
shared
public
require
daslib
/
clargs
require
daslib
/
rtti
require
daslib
/
fio
require
strings
require
daslib
/
strings_boost
// ===== dynamic-name reads (the ONE sanctioned escape hatch) =====
// For names known only at runtime, and for ambient variables a registry lists but does not own
// (HOME, PROCESSOR_IDENTIFIER, ...). Same set-but-empty-is-unset rule as the loaders. Not for
// hot paths, and a LITERAL knob name through these must still be declared in the registry.
def
public
env_is_set
(
name
:
string
) :
bool
{
return
has_env_variable
(
name
)
&&
!
empty
(
get_env_variable
(
name
))
}
def
public
env_value_of
(
name
:
string
) :
string
{
return
get_env_variable
(
name
)
}
//! A hand-written doc row for knobs no struct field can tell the truth about (compile-time
//! constants, foreign variables) — appended to a section after its `write_env_info_rows`.
struct
public
EnvDocRow
{
name : string
kind : string
dflt : string
doc : string
}
def
public
write_env_row
(
var
w
:
StringBuilderWriter
;
name
,
kind
,
dflt
,
doc
:
string
) {
w
|
>
write
(
"| `
{
name
}
` |
{
kind
}
|
{
empty
(
dflt
) ?
"unset"
:
dflt
}
|
{
doc
}
|
\n
"
)
}
def
public
write_env_row
(
var
w
:
StringBuilderWriter
;
row
:
EnvDocRow
) {
write_env_row
(
w
,
row
.
name
,
row
.
kind
,
row
.
dflt
,
row
.
doc
)
}
def
public
write_env_info_rows
(
var
w
:
StringBuilderWriter
;
info
:
CommandInfo
) {
for
(
a
in
info
.
args
) {
var
kind
=
"number"
if
(
a
.
value_type
==
Type
.
tBool
) {
kind
=
"flag"
}
elif
(
a
.
value_type
==
Type
.
tString
) {
kind
=
a
.
is_path
?
"path"
:
"text"
}
var
dflt
=
a
.
default_doc
if
(
a
.
value_type
==
Type
.
tBool
) {
dflt
=
dflt
==
"true"
?
"on"
: (
dflt
==
"false"
?
"off"
:
dflt
)
}
write_env_row
(
w
,
a
.
env_name
,
kind
,
dflt
,
a
.
doc_string
)
}
}
def
public
write_env_section
(
var
w
:
StringBuilderWriter
;
title
,
note
:
string
) {
w
|
>
write
(
"
\n
##
{
title
}
\n\n
"
)
if
(
!
empty
(
note
)) {
w
|
>
write
(
"
{
note
}
\n\n
"
)
}
w
|
>
write
(
"| Variable | Type | Default | Effect |
\n
|---|---|---|---|
\n
"
)
}
//! The loader-semantics paragraph — clargs behaviour, so the wording is shared verbatim. The
//! registry's own header (title + where it generates from + the regen command) stays with the
//! registry, since those name its files.
def
public
write_env_doc_semantics
(
var
w
:
StringBuilderWriter
) {
w
|
>
write
(
"Types: **flag** is unset-means-default, `0`/`false`/`off`/`no` (any case) is false and
\n
"
)
w
|
>
write
(
"anything else true; **number** falls back to the default when unset or unparseable, with
\n
"
)
w
|
>
write
(
"a logged warning on garbage; **text** and **path** are taken verbatim. A SET-BUT-EMPTY
\n
"
)
w
|
>
write
(
"variable counts as unset everywhere. Every knob loads ONCE, at context init, into the
\n
"
)
w
|
>
write
(
"`g_env_*` globals - hot code reads struct fields, and `set_env_variable` after startup
\n
"
)
w
|
>
write
(
"is invisible (arm a child process's environment instead).
\n
"
)
}
//! Every env name an `[EnvConfig]` struct declares, appended in declaration order — feeds the
//! registry's `registered_env_names()`.
def
public
push_info_names
(
var
out
:
array
<
string
>
;
info
:
CommandInfo
) {
out
|
>
reserve
(
length
(
out
)
+
length
(
info
.
args
))
for
(
a
in
info
.
args
) {
out
|
>
push
(
a
.
env_name
)
}
}
//! The generator-driver body: write the rendered doc, log the outcome. Callers pass an
//! absolute path (usually `{get_das_root()}/...`).
def
public
save_generated_doc
(
path
,
body
:
string
) :
bool
{
var
f
=
fopen
(
path
,
"wb"
)
if
(
f
==
null
) {
to_log
(
LOG_ERROR
,
"env_registry: cannot write
{
path
}
\n
"
)
return
false
}
fwrite
(
f
,
body
)
fclose
(
f
)
to_log
(
LOG_INFO
,
"env_registry: wrote
{
path
}
(
{
long_length
(
body
)
}
bytes)
\n
"
)
return
true
}
let
public
ENV_READ_MARKERS
=
[
"get_env_variable(
\"
"
,
"has_env_variable(
\"
"
,
"env_config_flag(
\"
"
,
"env_config_int(
\"
"
,
"env_config_int64(
\"
"
,
"env_config_float(
\"
"
,
"env_config_string(
\"
"
,
"env_config_text(
\"
"
]
let
public
ENV_SANCTIONED_MARKERS
=
[
"env_is_set(
\"
"
,
"env_value_of(
\"
"
]
let
public
ENV_WRITE_MARKERS
=
[
"set_env_variable(
\"
"
]
let
public
ENV_BANNED_HELPERS
=
[
"def private env_or("
,
"def env_or("
,
"def private pf_env_int("
,
"def private win_env_int("
,
"def env_int64("
,
"def private env_int64("
,
"def env_int("
,
"def private env_int("
,
"def env_str("
,
"def private env_str("
,
"def env_flag("
,
"def private env_flag("
,
"def env_int64_min("
,
"def private env_int64_min("
]
def
private
skip_path
(
path
:
string
;
skip
:
array
<
string
>
) :
bool
{
let
p
=
replace
(
path
,
"
\\
"
,
"/"
)
if
(
find
(
p
,
"_aot_generated"
)
>
=
0
) {
return
true
}
for
(
s
in
skip
) {
if
(
find
(
p
,
s
)
>
=
0
) {
return
true
}
}
return
false
}
def
private
walk_das
(
dirpath
:
string
;
skip
:
array
<
string
>
;
blk
:
block
<
(
path
:
string
;
text
:
string
) :
void
>) {
dir
(
dirpath
)
$
(name : string) {
return
if
(
name
==
"."
||
name
==
".."
)
let
full
=
"
{
dirpath
}
/
{
name
}
"
if
(
stat
(
full
).
is_dir
) {
return
if
(
name
==
"_aot_generated"
||
name
==
"_llvm_aot_generated"
)
walk_das
(
full
,
skip
,
blk
)
}
elif
(
ends_with
(
name
,
".das"
)
&&
!
skip_path
(
full
,
skip
)) {
let
text
=
fread
(
full
)
if
(
!
empty
(
text
)) {
blk
|
>
invoke
(
full
,
text
)
}
}
}
}
def
private
collect_names
(
text
:
string
;
markers
:
array
<
string
>
;
var
out
:
table
<
string
>
) {
peek_data
(
text
)
$
(d) {
for
(
marker
in
markers
) {
var
from
=
0
while
(
true
) {
let
hit
=
find
(
d
,
marker
,
from
)
break
if
(
hit
<
0
)
let
start
=
hit
+
length
(
marker
)
let
close
=
find
(
d
,
"
\"
"
,
start
)
break
if
(
close
<
0
)
let
name
=
slice
(
d
,
start
,
close
)
if
(
!
empty
(
name
)
&&
!
key_exists
(
out
,
name
)) {
out
|
>
insert
(
name
)
}
from
=
close
+
1
}
}
}
}
//! Files under `roots` (das-root-relative) that read the environment raw — for the strict
//! "knobs are `g_env_*` fields" check. `skip` = path substrings to exempt (the registry file,
//! the test itself).
def
public
scan_env_raw_reads
(
roots
,
skip
:
array
<
string
>
) :
array
<
string
> {
var
offenders
:
array
<
string
>
for
(
root
in
roots
) {
walk_das
(
"
{
get_das_root
()
}
/
{
root
}
"
,
skip
)
$
(path, text) {
for
(
marker
in
ENV_READ_MARKERS
) {
if
(
find
(
text
,
marker
)
>
=
0
) {
offenders
|
>
push
(
"
{
path
}
:
{
marker
}
...
\"
)"
)
break
}
}
}
}
return
<
-
offenders
}
//! Every literal env name read, written, or dynamically probed under the roots, plus the file
//! count (a coverage floor: a broken walk must not pass vacuously).
def
public
scan_env_used_names
(
roots
,
skip
:
array
<
string
>
;
var
used
:
table
<
string
>
) :
int
{
var
files
=
0
for
(
root
in
roots
) {
walk_das
(
"
{
get_das_root
()
}
/
{
root
}
"
,
skip
)
$
(_path, text) {
files
++
collect_names
(
text
,
ENV_READ_MARKERS
,
used
)
collect_names
(
text
,
ENV_SANCTIONED_MARKERS
,
used
)
collect_names
(
text
,
ENV_WRITE_MARKERS
,
used
)
}
}
return
files
}
//! Files under the roots re-declaring a private env-reader helper.
def
public
scan_env_banned_helpers
(
roots
,
skip
:
array
<
string
>
) :
array
<
string
> {
var
offenders
:
array
<
string
>
for
(
root
in
roots
) {
walk_das
(
"
{
get_das_root
()
}
/
{
root
}
"
,
skip
)
$
(path, text) {
for
(
sig
in
ENV_BANNED_HELPERS
) {
if
(
find
(
text
,
sig
)
>
=
0
) {
offenders
|
>
push
(
"
{
base_name
(
path
)
}
:
{
sig
}
...)"
)
}
}
}
}
return
<
-
offenders
}
//! Names in `used` with no declaration. Ambient variables the registry lists but does not
//! own (HOME, PROCESSOR_IDENTIFIER, ...) belong in `declared` too — fold them into the
//! registry's `registered_env_names()`.
def
public
env_undeclared_names
(
used
:
table
<
string
>
;
declared
:
array
<
string
>
) :
array
<
string
> {
var
known
:
table
<
string
>
for
(
n
in
declared
) {
known
|
>
insert
(
n
)
}
var
missing
<
-
[
for
(
n
in
keys
(
used
));
n
;
where
!
key_exists
(
known
,
n
)]
delete
known
return
<
-
missing
}
//! Duplicate declarations across the registry's area structs.
def
public
env_duplicate_names
(
names
:
array
<
string
>
) :
array
<
string
> {
var
seen
:
table
<
string
>
var
dupes
:
array
<
string
>
for
(
n
in
names
) {
if
(
key_exists
(
seen
,
n
)) {
dupes
|
>
push
(
n
)
}
else
{
seen
|
>
insert
(
n
)
}
}
delete
seen
return
<
-
dupes
}
//! Rendered doc rows whose Effect column is empty.
def
public
env_undocumented_rows
(
md
:
string
) :
array
<
string
> {
var
undocumented
:
array
<
string
>
for
(
line
in
split
(
md
,
"
\n
"
)) {
continue
if
(
!
starts_with
(
line
,
"| `"
))
var
cols
<
-
split
(
line
,
"|"
)
if
(
length
(
cols
)
>
=
5
&&
empty
(
strip
(
cols
[
4
]))) {
undocumented
|
>
push
(
strip
(
cols
[
1
]))
}
delete
cols
}
return
<
-
undocumented
}
Back
|
FazBrowse Home
|
New Git URL