Skip to content

Commit 5a044e6

Browse files
committed
[cc] include_path, other minor fixes
1 parent ad6b0e7 commit 5a044e6

File tree

5 files changed

+196
-136
lines changed

5 files changed

+196
-136
lines changed

cc/cflow.rs

Lines changed: 59 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ fn extract_calls_from_expr(
162162
expr: &posixutils_cc::parse::ast::Expr,
163163
strings: &StringTable,
164164
calls: &mut Vec<String>,
165-
variables: &mut Vec<String>,
166165
) {
167166
match &expr.kind {
168167
ExprKind::Call { func, args } => {
@@ -174,76 +173,70 @@ fn extract_calls_from_expr(
174173
}
175174
}
176175
// Recurse into function expression and arguments
177-
extract_calls_from_expr(func, strings, calls, variables);
176+
extract_calls_from_expr(func, strings, calls);
178177
for arg in args {
179-
extract_calls_from_expr(arg, strings, calls, variables);
180-
}
181-
}
182-
ExprKind::Ident { name } => {
183-
let var_name = strings.get(*name).to_string();
184-
if !variables.contains(&var_name) {
185-
variables.push(var_name);
178+
extract_calls_from_expr(arg, strings, calls);
186179
}
187180
}
188181
ExprKind::Unary { operand, .. } => {
189-
extract_calls_from_expr(operand, strings, calls, variables);
182+
extract_calls_from_expr(operand, strings, calls);
190183
}
191184
ExprKind::Binary { left, right, .. } => {
192-
extract_calls_from_expr(left, strings, calls, variables);
193-
extract_calls_from_expr(right, strings, calls, variables);
185+
extract_calls_from_expr(left, strings, calls);
186+
extract_calls_from_expr(right, strings, calls);
194187
}
195188
ExprKind::Assign { target, value, .. } => {
196-
extract_calls_from_expr(target, strings, calls, variables);
197-
extract_calls_from_expr(value, strings, calls, variables);
189+
extract_calls_from_expr(target, strings, calls);
190+
extract_calls_from_expr(value, strings, calls);
198191
}
199192
ExprKind::PostInc(e) | ExprKind::PostDec(e) => {
200-
extract_calls_from_expr(e, strings, calls, variables);
193+
extract_calls_from_expr(e, strings, calls);
201194
}
202195
ExprKind::Conditional {
203196
cond,
204197
then_expr,
205198
else_expr,
206199
} => {
207-
extract_calls_from_expr(cond, strings, calls, variables);
208-
extract_calls_from_expr(then_expr, strings, calls, variables);
209-
extract_calls_from_expr(else_expr, strings, calls, variables);
200+
extract_calls_from_expr(cond, strings, calls);
201+
extract_calls_from_expr(then_expr, strings, calls);
202+
extract_calls_from_expr(else_expr, strings, calls);
210203
}
211204
ExprKind::Member { expr, .. } | ExprKind::Arrow { expr, .. } => {
212-
extract_calls_from_expr(expr, strings, calls, variables);
205+
extract_calls_from_expr(expr, strings, calls);
213206
}
214207
ExprKind::Index { array, index } => {
215-
extract_calls_from_expr(array, strings, calls, variables);
216-
extract_calls_from_expr(index, strings, calls, variables);
208+
extract_calls_from_expr(array, strings, calls);
209+
extract_calls_from_expr(index, strings, calls);
217210
}
218211
ExprKind::Cast { expr, .. } => {
219-
extract_calls_from_expr(expr, strings, calls, variables);
212+
extract_calls_from_expr(expr, strings, calls);
220213
}
221214
ExprKind::SizeofExpr(e) => {
222-
extract_calls_from_expr(e, strings, calls, variables);
215+
extract_calls_from_expr(e, strings, calls);
223216
}
224217
ExprKind::Comma(exprs) => {
225218
for e in exprs {
226-
extract_calls_from_expr(e, strings, calls, variables);
219+
extract_calls_from_expr(e, strings, calls);
227220
}
228221
}
229222
ExprKind::InitList { elements } | ExprKind::CompoundLiteral { elements, .. } => {
230223
for elem in elements {
231-
extract_calls_from_expr(&elem.value, strings, calls, variables);
224+
extract_calls_from_expr(&elem.value, strings, calls);
232225
}
233226
}
234227
// Variadic builtins
235228
ExprKind::VaStart { ap, .. } => {
236-
extract_calls_from_expr(ap, strings, calls, variables);
229+
extract_calls_from_expr(ap, strings, calls);
237230
}
238231
ExprKind::VaArg { ap, .. } => {
239-
extract_calls_from_expr(ap, strings, calls, variables);
232+
extract_calls_from_expr(ap, strings, calls);
240233
}
241234
ExprKind::VaEnd { ap } => {
242-
extract_calls_from_expr(ap, strings, calls, variables);
235+
extract_calls_from_expr(ap, strings, calls);
243236
}
244237
ExprKind::VaCopy { dest, src } => {
245-
extract_calls_from_expr(dest, strings, calls, variables);
246-
extract_calls_from_expr(src, strings, calls, variables);
238+
extract_calls_from_expr(dest, strings, calls);
239+
extract_calls_from_expr(src, strings, calls);
247240
}
248241
// Other builtins with arguments
249242
ExprKind::Bswap16 { arg }
@@ -259,35 +252,30 @@ fn extract_calls_from_expr(
259252
| ExprKind::Popcountl { arg }
260253
| ExprKind::Popcountll { arg }
261254
| ExprKind::Alloca { size: arg } => {
262-
extract_calls_from_expr(arg, strings, calls, variables);
255+
extract_calls_from_expr(arg, strings, calls);
263256
}
264-
// Literals and other terminals - no recursion needed
257+
// Literals, identifiers, and other terminals - no recursion needed
265258
_ => {}
266259
}
267260
}
268261

269262
/// Walk a statement to find function calls
270-
fn extract_calls_from_stmt(
271-
stmt: &Stmt,
272-
strings: &StringTable,
273-
calls: &mut Vec<String>,
274-
variables: &mut Vec<String>,
275-
) {
263+
fn extract_calls_from_stmt(stmt: &Stmt, strings: &StringTable, calls: &mut Vec<String>) {
276264
match stmt {
277265
Stmt::Empty => {}
278266
Stmt::Expr(expr) => {
279-
extract_calls_from_expr(expr, strings, calls, variables);
267+
extract_calls_from_expr(expr, strings, calls);
280268
}
281269
Stmt::Block(items) => {
282270
for item in items {
283271
match item {
284272
posixutils_cc::parse::ast::BlockItem::Statement(s) => {
285-
extract_calls_from_stmt(s, strings, calls, variables);
273+
extract_calls_from_stmt(s, strings, calls);
286274
}
287275
posixutils_cc::parse::ast::BlockItem::Declaration(decl) => {
288276
for d in &decl.declarators {
289277
if let Some(init) = &d.init {
290-
extract_calls_from_expr(init, strings, calls, variables);
278+
extract_calls_from_expr(init, strings, calls);
291279
}
292280
}
293281
}
@@ -299,19 +287,19 @@ fn extract_calls_from_stmt(
299287
then_stmt,
300288
else_stmt,
301289
} => {
302-
extract_calls_from_expr(cond, strings, calls, variables);
303-
extract_calls_from_stmt(then_stmt, strings, calls, variables);
290+
extract_calls_from_expr(cond, strings, calls);
291+
extract_calls_from_stmt(then_stmt, strings, calls);
304292
if let Some(else_s) = else_stmt {
305-
extract_calls_from_stmt(else_s, strings, calls, variables);
293+
extract_calls_from_stmt(else_s, strings, calls);
306294
}
307295
}
308296
Stmt::While { cond, body } => {
309-
extract_calls_from_expr(cond, strings, calls, variables);
310-
extract_calls_from_stmt(body, strings, calls, variables);
297+
extract_calls_from_expr(cond, strings, calls);
298+
extract_calls_from_stmt(body, strings, calls);
311299
}
312300
Stmt::DoWhile { body, cond } => {
313-
extract_calls_from_stmt(body, strings, calls, variables);
314-
extract_calls_from_expr(cond, strings, calls, variables);
301+
extract_calls_from_stmt(body, strings, calls);
302+
extract_calls_from_expr(cond, strings, calls);
315303
}
316304
Stmt::For {
317305
init,
@@ -322,37 +310,37 @@ fn extract_calls_from_stmt(
322310
if let Some(i) = init {
323311
match i {
324312
posixutils_cc::parse::ast::ForInit::Expression(e) => {
325-
extract_calls_from_expr(e, strings, calls, variables);
313+
extract_calls_from_expr(e, strings, calls);
326314
}
327315
posixutils_cc::parse::ast::ForInit::Declaration(d) => {
328316
for decl in &d.declarators {
329317
if let Some(init_expr) = &decl.init {
330-
extract_calls_from_expr(init_expr, strings, calls, variables);
318+
extract_calls_from_expr(init_expr, strings, calls);
331319
}
332320
}
333321
}
334322
}
335323
}
336324
if let Some(c) = cond {
337-
extract_calls_from_expr(c, strings, calls, variables);
325+
extract_calls_from_expr(c, strings, calls);
338326
}
339327
if let Some(p) = post {
340-
extract_calls_from_expr(p, strings, calls, variables);
328+
extract_calls_from_expr(p, strings, calls);
341329
}
342-
extract_calls_from_stmt(body, strings, calls, variables);
330+
extract_calls_from_stmt(body, strings, calls);
343331
}
344332
Stmt::Return(Some(expr)) => {
345-
extract_calls_from_expr(expr, strings, calls, variables);
333+
extract_calls_from_expr(expr, strings, calls);
346334
}
347335
Stmt::Switch { expr, body } => {
348-
extract_calls_from_expr(expr, strings, calls, variables);
349-
extract_calls_from_stmt(body, strings, calls, variables);
336+
extract_calls_from_expr(expr, strings, calls);
337+
extract_calls_from_stmt(body, strings, calls);
350338
}
351339
Stmt::Case(expr) => {
352-
extract_calls_from_expr(expr, strings, calls, variables);
340+
extract_calls_from_expr(expr, strings, calls);
353341
}
354342
Stmt::Label { stmt, .. } => {
355-
extract_calls_from_stmt(stmt, strings, calls, variables);
343+
extract_calls_from_stmt(stmt, strings, calls);
356344
}
357345
_ => {}
358346
}
@@ -441,6 +429,7 @@ fn process_file(
441429
graph: &mut CallGraph,
442430
defines: &[String],
443431
undefines: &[String],
432+
include_paths: &[String],
444433
) -> io::Result<()> {
445434
// Read file content
446435
let file = File::open(path)?;
@@ -462,8 +451,15 @@ fn process_file(
462451

463452
// Preprocess
464453
let target = Target::host();
465-
let preprocessed =
466-
preprocess_with_defines(tokens, &target, &mut strings, path, defines, undefines);
454+
let preprocessed = preprocess_with_defines(
455+
tokens,
456+
&target,
457+
&mut strings,
458+
path,
459+
defines,
460+
undefines,
461+
include_paths,
462+
);
467463

468464
// Create symbol table and type table
469465
let mut symbols = SymbolTable::new();
@@ -487,11 +483,9 @@ fn process_file(
487483
let line = func.pos.line;
488484

489485
let mut calls = Vec::new();
490-
let mut _variables = Vec::new();
491-
extract_calls_from_stmt(&func.body, &strings, &mut calls, &mut _variables);
486+
extract_calls_from_stmt(&func.body, &strings, &mut calls);
492487

493-
// Filter out self-recursion representation for cleaner output
494-
// and filter based on include options
488+
// Filter calls based on include options (e.g., underscore names)
495489
calls.retain(|c| graph.should_include(c));
496490

497491
let info = FunctionInfo {
@@ -642,6 +636,7 @@ fn main() -> ExitCode {
642636
&mut graph,
643637
&args.defines,
644638
&args.undefines,
639+
&args.include_paths,
645640
) {
646641
eprintln!("cflow: {}: {}", file, e);
647642
}

cc/ctags.rs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use posixutils_cc::token::{preprocess_with_defines, StreamTable, Tokenizer};
2323
use posixutils_cc::types::TypeTable;
2424
use std::collections::BTreeMap;
2525
use std::fs::{self, File, OpenOptions};
26-
use std::io::{self, BufReader, Read, Write};
26+
use std::io::{self, Write};
2727
use std::path::Path;
2828
use std::process::ExitCode;
2929

@@ -92,12 +92,6 @@ impl TagEntry {
9292
// Source File Processing
9393
// ============================================================================
9494

95-
/// Read file contents and split into lines
96-
fn read_file_lines(path: &str) -> io::Result<Vec<String>> {
97-
let content = fs::read_to_string(path)?;
98-
Ok(content.lines().map(String::from).collect())
99-
}
100-
10195
/// Get the line content for a given line number (1-based)
10296
fn get_line_content(lines: &[String], line_num: u32) -> String {
10397
if line_num == 0 || line_num as usize > lines.len() {
@@ -111,14 +105,9 @@ fn get_line_content(lines: &[String], line_num: u32) -> String {
111105
fn process_file(path: &str, streams: &mut StreamTable) -> io::Result<Vec<TagEntry>> {
112106
let mut tags = Vec::new();
113107

114-
// Read file content
115-
let file = File::open(path)?;
116-
let mut reader = BufReader::new(file);
117-
let mut buffer = Vec::new();
118-
reader.read_to_end(&mut buffer)?;
119-
120-
// Also read as lines for line content extraction
121-
let lines = read_file_lines(path)?;
108+
// Read file content once
109+
let content = fs::read_to_string(path)?;
110+
let lines: Vec<String> = content.lines().map(String::from).collect();
122111

123112
// Extract macro tags first (before preprocessing removes them)
124113
extract_macro_tags(&lines, path, &mut tags);
@@ -131,7 +120,7 @@ fn process_file(path: &str, streams: &mut StreamTable) -> io::Result<Vec<TagEntr
131120

132121
// Tokenize
133122
let tokens = {
134-
let mut tokenizer = Tokenizer::new(&buffer, stream_id, &mut strings);
123+
let mut tokenizer = Tokenizer::new(content.as_bytes(), stream_id, &mut strings);
135124
tokenizer.tokenize()
136125
};
137126

@@ -144,6 +133,7 @@ fn process_file(path: &str, streams: &mut StreamTable) -> io::Result<Vec<TagEntr
144133
path,
145134
&[], // No extra defines
146135
&[], // No undefines
136+
&[], // No include paths
147137
);
148138

149139
// Create symbol table and type table
@@ -215,11 +205,46 @@ fn process_file(path: &str, streams: &mut StreamTable) -> io::Result<Vec<TagEntr
215205
Ok(tags)
216206
}
217207

208+
/// Check whether a line contains a typedef definition for the given name.
209+
///
210+
/// This is a lightweight heuristic that:
211+
/// - Ignores anything following `//` or `/*` on the line.
212+
/// - Requires `typedef` to appear as a separate token.
213+
/// - Requires the typedef name to appear as an identifier-like token
214+
/// (allowing for trailing punctuation like `;` or `,`).
215+
fn is_typedef_line(line: &str, name: &str) -> bool {
216+
// Strip off line comments and simple block comment starts.
217+
let mut code = line;
218+
if let Some(idx) = code.find("//") {
219+
code = &code[..idx];
220+
}
221+
if let Some(idx) = code.find("/*") {
222+
code = &code[..idx];
223+
}
224+
let code = code.trim();
225+
if code.is_empty() {
226+
return false;
227+
}
228+
let mut has_typedef = false;
229+
let mut has_name = false;
230+
for raw_token in code.split_whitespace() {
231+
if raw_token == "typedef" {
232+
has_typedef = true;
233+
continue;
234+
}
235+
// Strip trailing non-identifier characters (e.g., ';', ',', ')').
236+
let cleaned = raw_token.trim_end_matches(|c: char| !(c.is_alphanumeric() || c == '_'));
237+
if cleaned == name {
238+
has_name = true;
239+
}
240+
}
241+
has_typedef && has_name
242+
}
243+
218244
/// Find the line number where a typedef is defined
219245
fn find_typedef_line(lines: &[String], name: &str) -> Option<u32> {
220246
for (i, line) in lines.iter().enumerate() {
221-
// Simple heuristic: look for "typedef ... name" or "typedef ... name;"
222-
if line.contains("typedef") && line.contains(name) {
247+
if is_typedef_line(line, name) {
223248
return Some((i + 1) as u32);
224249
}
225250
}

0 commit comments

Comments
 (0)