自动转换C代码

时间:2018-07-04 21:44:27

标签: c regex visual-studio

假设我有以下简单代码:

void xorFunction (unsigned char output[], unsigned char a[], unsigned char b[], size_t length)
{
    for(unsigned int i = 0; i < length; i++)
        output[i] = a[i] ^ b[i];
}

int main()
{
    unsigned char input[16] = { ... };
    unsigned char mask[16] = { ... };
    unsigned char output[16];

    xorFunction(output, input, mask, 16);
    xorFunction(mask, output, input, 16);
    xorFunction(input, mask, output, 16);

    return 0;
}

突然之间,我想摆脱xorFunction,所以我决定写for(i = 0; i < length; i++) ...而不是xorFunction(...);

如何使用文本编辑器的查找和替换工具来做到这一点?

它看起来可能像这样:

Find: xorFunction(a, b, c, d);

Replace with: for(unsigned int i = 0; i < d; i++) a[i] = b[i] ^ c[i];
with a, b, c and d parameters of xorFunction.

abcd如何成为由查找和替换工具处理的变量?我想正则表达式在这种情况下会很有用,但我不知道如何。

3 个答案:

答案 0 :(得分:2)

Coccinelle ("semantic patches for C")非常适合这种转换:

  

Coccinelle是一个程序匹配和转换引擎,它提供语言SmPL(语义补丁语言)来指定C代码中所需的匹配和转换。 Coccinelle最初的目标是在Linux中执行附带进化。这样的演变包括响应库API的演变而在客户端代码中所需的更改,并且可能包括修改,例如重命名功能,添加其值在某种程度上取决于上下文的功能自变量以及重组数据结构。除了附带的发展之外,Coccinelle(我们和其他人)也成功地用于发现和修复系统代码中的错误。


另一个选项是Using Clang as a Library。虽然通常它比编写Coccinelle的语义补丁(甚至考虑使用Clang Python绑定)还要复杂得多,但是在这种情况下,它应该不会太难。它的优点是您也可以解析C ++。

答案 1 :(得分:0)

您不能在正则表达式中使用变量。

xorFunction \(\s*[^,]+,\s*[^,]+,\s*[^,]+,\s*[^\)]+\)这将是用于捕获xorFunction块的正则表达式,但是纯正则表达式中不能包含变量。您可以尝试寻找其他方法来做到这一点,但我认为手动进行操作会更快(复制参数,使用正则表达式,替换)

答案 2 :(得分:0)

可以使用宏吗?这可能就足够了:

import Foundation
import UIKit
import CoreLocation
import MapKit

class ViewController: UIViewController, MKMapViewDelegate,        CLLocationManagerDelegate {

@IBOutlet weak var mapView: MKMapView!

var locationManager = CLLocationManager()

override func viewDidLoad() {
    super.viewDidLoad()

    locationManager = CLLocationManager()
    mapView.delegate = self
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.requestAlwaysAuthorization()
    locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    locationManager.startUpdatingLocation()
    mapView.showsUserLocation = true
    mapView.setUserTrackingMode(.follow, animated: true)

    let title = "Oakville Test"
    let coordinate = CLLocationCoordinate2DMake(43.477521, -79.712430)
    let regionRadius = 150.0

    // setup region
    let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude), radius: regionRadius, identifier: title)
    region.notifyOnEntry = true
    region.notifyOnExit = true
    locationManager.startMonitoring(for: region)
    locationManager.startUpdatingLocation()

    // setup annotation
    let annotationView = MKPointAnnotation()
    annotationView.coordinate = coordinate;
    annotationView.title = "\(title)";
    mapView.addAnnotation(annotationView)

    // setup circle
    let circle = MKCircle(center: coordinate, radius: regionRadius)
    mapView.add(circle)
}

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer! {
    if overlay is MKPolyline {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.strokeColor = UIColor.blue.withAlphaComponent(0.6)
        renderer.lineWidth = 5.0
        renderer.fillColor = UIColor.blue.withAlphaComponent(0.7)
        return renderer
    } else {
        let circleRenderer = MKCircleRenderer(overlay: overlay)
        circleRenderer.strokeColor = UIColor.red.withAlphaComponent(0.4)
        circleRenderer.lineWidth = 1.0
        circleRenderer.fillColor = UIColor.red.withAlphaComponent(0.4)
        return circleRenderer
    }
    return nil
}

func showAlert(_ title: String) {
    let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
    let noAction = UIAlertAction(title: "No", style: .default, handler: nil)
    let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: nil)
    alert.addAction(yesAction)
    alert.addAction(noAction)
    self.present(alert, animated: true, completion: nil)
}

func locationManager(_ manager: CLLocationManager, didStartMonitoringFor region: CLRegion) {
    print("The monitored regions are: \(manager.monitoredRegions)")
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate
    print("locations = \(locValue.latitude) \(locValue.longitude)")
}

func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
    showAlert("You are at \(region.identifier)!")
}

func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
    showAlert("leaving \(region.identifier).")
    }
}

更接近防弹的版本将添加一些宏语言:

#define xorFunction(a, b, c, d) for (int i = 0; i < d; i++) a[i] = b[i] ^ c[i]

如果您有一个表达式使用#define xorFunction(a, b, c, d) do { for (int i = 0; i < (d); i++) (a)[i] = (b)[i] ^ (c)[i]; } while (0) 作为对i的调用中的变量,这仍然会遇到问题,例如xorFunction()。避免这种情况很困难-使用宏将xorFunction(…, &data[i], …)与行号或附近的行连接起来可能是一个足够健壮的选择。


更强大的代码可能会使用:

i

我使用的#define CONCATENATE(v, n) v ## _ ## n #define EVALUATE(v, n) CONCATENATE(v, n) #define V(x) EVALUATE(x, __LINE__) #define xorFunction(a, b, c, d) \ do { \ for (int V(i) = 0; V(i) < (d); V(i)++) \ (a)[V(i)] = (b)[V(i)] ^ (c)[V(i)]; \ } while (0) int main(void) { unsigned char input[16] = { ... }; unsigned char mask[16] = { ... }; unsigned char output[16]; xorFunction(output, input, mask, 16); xorFunction(mask, output, input, 16); xorFunction(input, mask, output, 16); for (int i = 4; i < 8; i++) xorFunction(&ouput[i], &input[i], &mask[i], sizeof(mask)-i); return 0; } 的输出是:

cpp

请注意,如果没有通过# 1 "xx.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "xx.c" # 11 "xx.c" int main(void) { unsigned char input[16] = { ... }; unsigned char mask[16] = { ... }; unsigned char output[16]; do { for (int i_17 = 0; i_17 < (16); i_17++) (output)[i_17] = (input)[i_17] ^ (mask)[i_17]; } while (0); do { for (int i_18 = 0; i_18 < (16); i_18++) (mask)[i_18] = (output)[i_18] ^ (input)[i_18]; } while (0); do { for (int i_19 = 0; i_19 < (16); i_19++) (input)[i_19] = (mask)[i_19] ^ (output)[i_19]; } while (0); for (int i = 4; i < 8; i++) do { for (int i_21 = 0; i_21 < (sizeof(mask)-i); i_21++) (&ouput[i])[i_21] = (&input[i])[i_21] ^ (&mask[i])[i_21]; } while (0); return 0; } 宏命名变量,则V到达{{1时,(&mask[i])[i]这样的表达式将访问mask数组范围之外的数据。 }},并且除非i8,否则i小于8时不会访问预期的内容。