Skip to content

Commit fc0e7e3

Browse files
author
Simao Gomes Viana
committed
Add support for "function" defines
This is supported now: #define max(a, b) ((a) > (b) ? (a) : (b)) Also move the whole resolving thing to a separate function
1 parent 7fa682c commit fc0e7e3

File tree

3 files changed

+163
-35
lines changed

3 files changed

+163
-35
lines changed

example

+11-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
#define EXAMPLE2
2020
#define EXAMPLE3
2121
#define EXAMPLE4 You know
22+
#define prnt(str, fmt) printf(str, fmt)
23+
#define sup(str) str
24+
#define COOL_NUM 2
25+
#define max(a, b) ((a) > (b) ? (a) : (b))
26+
// Another variant just to make sure we can shuffle the stuff
27+
#define min(b, a) ((a) > (b) ? (b) : (a))
28+
#define max2(b, a) max(a, b)
2229

2330
#define HOW_I_AM I'm fine
2431

@@ -58,8 +65,11 @@ HOW_I_AM
5865
#ifdef EX1
5966
#ifndef EXAMPLE5
6067
#ifdef EXAMPLE4
61-
printf(nice-thing-to-replace)
68+
prnt(nice-thing-to-replace, sup("%s"))sup(;)
6269
#endif
70+
max(8, 10*4)
71+
min(5*4, 2+COOL_NUM)
72+
max2(9, COOL_NUM)
6373
#endif
6474
#endif
6575

js/index.js

+148-33
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ function Define (name, value) {
8181
this.value = value || ''
8282
}
8383

84+
function FuncDefine (name, args, func) {
85+
this.name = name
86+
this.args = args
87+
this.func = func
88+
}
89+
8490
var defines = []
8591
var expectEndifCount = 0
8692
var skipCount = 0
@@ -125,19 +131,149 @@ function createDefineFromLine (line, rl, linenum) {
125131
if (debug) {
126132
console.log(` afterdef: ${afterdef}`)
127133
}
128-
var hasValue = afterdef.indexOf(' ') !== -1
129-
var name = afterdef.substring(0, hasValue ? afterdef.indexOf(' ')
130-
: afterdef.length)
134+
let spaceIx = afterdef.indexOf(' ')
135+
let brIx = afterdef.indexOf('(')
136+
let clBrIx = afterdef.indexOf(')')
137+
let isFunc = false
138+
if (brIx !== -1 && brIx < spaceIx) {
139+
isFunc = true
140+
if (clBrIx === -1) {
141+
console.error(`Error: Unterminated function definition on line ${linenum}`)
142+
console.error(` Missing ')'.`)
143+
console.error(` ${line}`)
144+
rc = 2
145+
rl.close()
146+
return
147+
}
148+
if (afterdef.charAt(clBrIx + 1) == ' ') {
149+
spaceIx = clBrIx + 1
150+
} else {
151+
spaceIx = -1
152+
}
153+
}
154+
var hasValue = spaceIx !== -1
155+
var name = afterdef.substring(0, hasValue ? spaceIx : afterdef.length)
131156
if (!name) {
132157
console.error(`Error: No name specified for define, line ${linenum}`)
133158
console.error(` ${line}`)
134159
rc = 2
135160
rl.close()
136161
return
137162
}
138-
var value = hasValue ? afterdef.substring(afterdef.indexOf(' ') + 1,
139-
afterdef.length) : ''
140-
return new Define(name, value)
163+
var value = hasValue ? afterdef.substring(spaceIx + 1, afterdef.length)
164+
: ''
165+
let args, func, funcName
166+
if (isFunc) {
167+
funcName = name.substring(0, name.indexOf('(')).trim()
168+
args = []
169+
let argsStr = name.substring(name.indexOf('(') + 1, name.indexOf(')'))
170+
argsStr.split(',').forEach((s) => {
171+
let str = s.trim()
172+
args.push(str)
173+
})
174+
func = value
175+
}
176+
return isFunc ? new FuncDefine(funcName, args, func) : new Define(name, value)
177+
}
178+
179+
function resolveLine (lineToResolve, linenum) {
180+
let resolvedLine = lineToResolve
181+
defines.forEach((e) => {
182+
if (e.value !== undefined) {
183+
let regex = new RegExp("(\\W|^)" + e.name + "(\\W|$)", "g")
184+
if (resolvedLine.match(regex)) {
185+
if (debug) {
186+
console.log(` Current line has define ${e.name}`)
187+
}
188+
let matches = regex.exec(resolvedLine)
189+
let newmatches = []
190+
let i = 0
191+
matches.forEach((match) => {
192+
if (match.length >= e.name.length) {
193+
if (debug) {
194+
console.log(` Match ${match}`)
195+
}
196+
newmatches.push([match.replace(e.name, e.value), i])
197+
}
198+
i++
199+
})
200+
i = 0
201+
newmatches.forEach((match) => {
202+
resolvedLine =
203+
resolvedLine.replace(matches[newmatches[i][1]], newmatches[i][0])
204+
i++
205+
})
206+
}
207+
} else if (e.func !== undefined) {
208+
// Example: \b[()\[\]{},; ]*prnt( *)[(][^,]*[)]
209+
let regexStr = "\\b[()\\[\\]{},; ]*?"
210+
let replRegexStr = e.name + "( *?)[(]"
211+
var i
212+
for (i = 0; i < e.args.length; i++) {
213+
replRegexStr += "[^,]+?,"
214+
}
215+
replRegexStr = replRegexStr.substring(0, replRegexStr.length - 1)
216+
replRegexStr += "[)]"
217+
regexStr += replRegexStr
218+
let finalReplRegex = new RegExp(replRegexStr)
219+
if (debug) {
220+
console.log(` regexStr: ${regexStr}`)
221+
}
222+
let regex = new RegExp(regexStr)
223+
while (resolvedLine.match(regex)) {
224+
if (debug) {
225+
console.log(` ${linenum} uses a function define!`)
226+
}
227+
let funcBody = e.func.valueOf()
228+
if (debug) {
229+
console.log(` Defined function body: ${funcBody}`)
230+
}
231+
let matches = regex.exec(resolvedLine)
232+
if (debug) {
233+
console.log(` All matches: \n${JSON.stringify(matches)}`)
234+
}
235+
let match = matches[0]
236+
if (match === undefined || match === null ||
237+
match.trim().length === 0) return
238+
if (debug) {
239+
console.log(` Processing match ${match}`)
240+
}
241+
let lineArgsStr = match.substring(
242+
match.indexOf('(') + 1, match.lastIndexOf(')'))
243+
let lineArgs = []
244+
if (lineArgsStr.indexOf(',') !== -1) {
245+
lineArgsStr.split(',').forEach((lineArg) => {
246+
lineArgs.push(lineArg.trim())
247+
})
248+
} else {
249+
lineArgs.push(lineArgsStr.trim())
250+
}
251+
if (debug) {
252+
console.log(` Line args: ${lineArgs}`)
253+
}
254+
i = 0
255+
e.args.forEach((arg) => {
256+
if (debug) {
257+
console.log(` Function body before replace: ${funcBody}`)
258+
}
259+
let replRegex = new RegExp("\\b" + arg + "\\b", "g")
260+
if (debug) {
261+
let replRegexMatches = replRegex.exec(funcBody)
262+
console.log(` Repl regex matches: ` +
263+
`${JSON.stringify(replRegexMatches)}`)
264+
}
265+
funcBody = funcBody.replace(replRegex, lineArgs[i])
266+
if (debug) {
267+
console.log(` Replaced ${arg} with ${lineArgs[i]}`)
268+
console.log(` New function body: ${funcBody}\n`)
269+
}
270+
i++
271+
})
272+
resolvedLine = resolvedLine.replace(finalReplRegex, funcBody)
273+
}
274+
}
275+
})
276+
return resolvedLine
141277
}
142278

143279
function processLine (rawline, inputfile, outputfile, rl, linenum, afterPause) {
@@ -265,33 +401,12 @@ function processLine (rawline, inputfile, outputfile, rl, linenum, afterPause) {
265401
}
266402
}})() === true) return true
267403
if (skipCount == 0 && printLine) {
268-
let resolvedLine = rawline.valueOf()
269-
defines.forEach((e) => {
270-
let regex = new RegExp("(\\W|^)" + e.name + "(\\W|$)", "g")
271-
if (rawline.match(regex)) {
272-
if (debug) {
273-
console.log(` Current line has define ${e.name}`)
274-
}
275-
let matches = regex.exec(resolvedLine)
276-
let newmatches = []
277-
let i = 0
278-
matches.forEach((match) => {
279-
if (match.length >= e.name.length) {
280-
if (debug) {
281-
console.log(` Match ${match}`)
282-
}
283-
newmatches.push([match.replace(e.name, e.value), i])
284-
}
285-
i++
286-
})
287-
i = 0
288-
newmatches.forEach((match) => {
289-
resolvedLine =
290-
resolvedLine.replace(matches[newmatches[i][1]], newmatches[i][0])
291-
i++
292-
})
293-
}
294-
})
404+
let resolvedLine = resolveLine(rawline.valueOf())
405+
let prevResolvedLine
406+
while (resolvedLine !== prevResolvedLine) {
407+
prevResolvedLine = resolvedLine.valueOf()
408+
resolvedLine = resolveLine(prevResolvedLine)
409+
}
295410
fs.appendFileSync(outputfile, `${resolvedLine}\n`)
296411
}
297412
}

output

+4-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ there
4747
How are you?
4848
I'm fine
4949

50-
printf("don't ask me!")
50+
printf("don't ask me!", "%s");
51+
((8) > (10*4) ? (8) : (10*4))
52+
((2+2) > (5*4) ? (5*4) : (2+2))
53+
((2) > (9) ? (2) : (9))
5154

5255
YOU_NEVER_KNOW_HOW_I_AM

0 commit comments

Comments
 (0)