Skip to content

Commit

Permalink
Merge pull request #283 from ggreer/language_options
Browse files Browse the repository at this point in the history
Language options
  • Loading branch information
ggreer committed Oct 26, 2013
2 parents cbcd88f + a3948d3 commit 04ec543
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}

bin_PROGRAMS = ag
ag_SOURCES = src/ignore.c src/ignore.h src/log.c src/log.h src/options.c src/options.h src/print.c src/print.h src/scandir.c src/scandir.h src/search.c src/search.h src/util.c src/util.h src/decompress.c src/decompress.h src/uthash.h src/main.c
ag_SOURCES = src/ignore.c src/ignore.h src/log.c src/log.h src/options.c src/options.h src/print.c src/print.h src/scandir.c src/scandir.h src/search.c src/search.h src/lang.c src/lang.h src/util.c src/util.h src/decompress.c src/decompress.h src/uthash.h src/main.c
ag_LDADD = ${PCRE_LIBS} ${LZMA_LIBS} -lz -lpthread

dist_man_MANS = doc/ag.1
Expand Down
6 changes: 3 additions & 3 deletions src/decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ static void* decompress_zlib(const void* buf, const int buf_len,
return NULL;
}

static void* decompress_lwz(const void* buf, const int buf_len,
static void* decompress_lzw(const void* buf, const int buf_len,
const char* dir_full_path, int* new_buf_len) {
(void)buf; (void)buf_len;
log_err("LWZ (UNIX compress) files not yet supported: %s", dir_full_path);
log_err("LZW (UNIX compress) files not yet supported: %s", dir_full_path);
*new_buf_len = 0;
return NULL;
}
Expand Down Expand Up @@ -184,7 +184,7 @@ void* decompress(const ag_compression_type zip_type, const void* buf, const int
case AG_GZIP:
return decompress_zlib(buf, buf_len, dir_full_path, new_buf_len);
case AG_COMPRESS:
return decompress_lwz(buf, buf_len, dir_full_path, new_buf_len);
return decompress_lzw(buf, buf_len, dir_full_path, new_buf_len);
case AG_ZIP:
return decompress_zip(buf, buf_len, dir_full_path, new_buf_len);
case AG_XZ:
Expand Down
95 changes: 95 additions & 0 deletions src/lang.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#include <stdlib.h>
#include <string.h>

#include "lang.h"
#include "util.h"

lang_spec_t langs[] = {
{"actionscript", {"as", "mxml"}},
{"ada", {"ada", "adb", "ads"}},
{"asm", {"asm", "s"}},
{"batch", {"bat", "cmd"}},
{"cc", {"c", "h", "xs"}},
{"cfmx", {"cfc", "cfm", "cfml"}},
{"clojure", {"clj"}},
{"cpp", {"cpp", "cc", "cxx", "m", "hpp", "hh", "h", "hxx"}},
{"csharp", {"cs"}},
{"css", {"css"}},
{"delphi", {"pas", "int", "dfm", "nfm", "dof", "dpk", "dproj", "groupproj", "bdsgroup", "bdsproj"}},
{"elisp", {"el"}},
{"erlang", {"erl", "hrl"}},
{"fortran", {"f", "f77", "f90", "f95", "f03", "for", "ftn", "fpp"}},
{"go", {"go"}},
{"groovy", {"groovy", "gtmpl", "gpp", "grunit"}},
{"haskell", {"hs", "lhs"}},
{"hh", {"h"}},
{"html", {"htm", "html", "shtml", "xhtml"}},
{"java", {"java", "properties"}},
{"js", {"js"}},
{"jsp", {"jsp", "jspx", "jhtm", "jhtml"}},
{"lisp", {"lisp", "lsp"}},
{"lua", {"lua"}},
{"m4", {"m4"}},
{"matlab", {"m"}},
{"make", {"Makefiles", "mk", "mak"}},
{"mason", {"mas", "mhtml", "mpl", "mtxt"}},
{"objc", {"m", "h"}},
{"objcpp", {"mm", "h"}},
{"ocaml", {"ml", "mli"}},
{"octave", {"m"}},
{"parrot", {"pir", "pasm", "pmc", "ops", "pod", "pg", "tg"}},
{"perl", {"pl", "pm", "pm6", "pod", "t"}},
{"php", {"php", "phpt", "php3", "php4", "php5", "phtml"}},
{"plone", {"pt", "cpt", "metadata", "cpy", "py"}},
{"python", {"py"}},
{"rake", {"Rakefiles"}},
{"rs", {"rs"}},
{"ruby", {"rb", "rhtml", "rjs", "rxml", "erb", "rake", "spec"}},
{"rust", {"rs"}},
{"salt", {"sls"}},
{"scala", {"scala"}},
{"scheme", {"scm", "ss"}},
{"shell", {"sh", "bash", "csh", "tcsh", "ksh", "zsh"}},
{"smalltalk", {"st"}},
{"sql", {"sql", "ctl"}},
{"tcl", {"tcl", "itcl", "itk"}},
{"tex", {"tex", "cls", "sty"}},
{"tt", {"tt", "tt2", "ttml"}},
{"vb", {"bas", "cls", "frm", "ctl", "vb", "resx"}},
{"verilog", {"v", "vh", "sv"}},
{"vhdl", {"vhd", "vhdl"}},
{"vim", {"vim"}},
{"yaml", {"yaml", "yml"}},
{"xml", {"xml", "dtd", "xsl", "xslt", "ent"}},
{NULL, {NULL}}
};

char* make_lang_regex(const char** extensions) {
int regex_capacity = 100;
char* regex = ag_malloc(regex_capacity);
int regex_length = 3;
int subsequent = 0;
const char** extension;

strcpy(regex, "\\.(");

for (extension = extensions; *extension; ++extension) {
int extension_length = strlen(*extension);
while (regex_length + extension_length + 3 + subsequent > regex_capacity) {
regex_capacity *= 2;
regex = ag_realloc(regex, regex_capacity);
}
if (subsequent) {
regex[regex_length++] = '|';
} else {
subsequent = 1;
}
strcpy(regex + regex_length, *extension);
regex_length += extension_length;
}

regex[regex_length++] = ')';
regex[regex_length++] = '$';
regex[regex_length++] = 0;
return regex;
}
22 changes: 22 additions & 0 deletions src/lang.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef LANG_H
#define LANG_H

#define MAX_EXTENSIONS 12
#define LANG_COUNT 56

typedef struct {
const char* name;
const char* extensions[MAX_EXTENSIONS];
} lang_spec_t;

extern lang_spec_t langs[];

/**
Convert a NULL-terminated array of language extensions
into a regular expression of the form \.(extension1|extension2...)$
Caller is responsible for freeing the returned string.
*/
char* make_lang_regex(const char** extensions);

#endif
32 changes: 30 additions & 2 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "config.h"
#include "ignore.h"
#include "options.h"
#include "lang.h"
#include "log.h"
#include "util.h"

Expand Down Expand Up @@ -162,9 +163,13 @@ void parse_options(int argc, char **argv, char **base_paths[], char **paths[]) {
struct stat statbuf;
int rv;

size_t longopts_len;
option_t* longopts;
char *lang_regex = NULL;

init_options();

struct option longopts[] = {
option_t base_longopts[] = {
{ "ackmate", no_argument, &opts.ackmate, 1 },
{ "ackmate-dir-filter", required_argument, NULL, 0 },
{ "after", required_argument, NULL, 'A' },
Expand Down Expand Up @@ -221,9 +226,18 @@ void parse_options(int argc, char **argv, char **base_paths[], char **paths[]) {
{ "version", no_argument, &version, 1 },
{ "word-regexp", no_argument, NULL, 'w' },
{ "workers", required_argument, NULL, 0 },
{ NULL, 0, NULL, 0 }
};

longopts_len = sizeof(base_longopts) / sizeof(option_t);
longopts = ag_malloc(sizeof(base_longopts) + sizeof(option_t) * LANG_COUNT);
memcpy(longopts, base_longopts, sizeof(base_longopts));

for (i = 0; i < LANG_COUNT; i++) {
option_t opt = { langs[i].name, no_argument, NULL, 0 };
longopts[i + longopts_len] = opt;
}
longopts[LANG_COUNT + sizeof(base_longopts)] = (option_t){ NULL, 0, NULL, 0 };

if (argc < 2) {
usage();
cleanup_ignore(root_ignores);
Expand Down Expand Up @@ -396,6 +410,20 @@ void parse_options(int argc, char **argv, char **base_paths[], char **paths[]) {
if (longopts[opt_index].flag != 0) {
break;
}

for (i = 0; i < LANG_COUNT; i++) {
if (strcmp(longopts[opt_index].name, langs[i].name) == 0) {
lang_regex = make_lang_regex(langs[i].extensions);
compile_study(&opts.file_search_regex, &opts.file_search_regex_extra, lang_regex, 0, 0);
break;
}
}
if (lang_regex) {
free(lang_regex);
lang_regex = NULL;
break;
}

log_err("option %s does not take a value", longopts[opt_index].name);
default:
usage();
Expand Down
2 changes: 2 additions & 0 deletions src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ typedef struct {
/* global options. parse_options gives it sane values, everything else reads from it */
cli_options opts;

typedef struct option option_t;

void init_options();
void parse_options(int argc, char **argv, char **base_paths[], char **paths[]);
void cleanup_options();
Expand Down

2 comments on commit 04ec543

@kjk
Copy link

@kjk kjk commented on 04ec543 Oct 29, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

longopts[LANG_COUNT + sizeof(base_longopts)] = (option_t){ NULL, 0, NULL, 0 };

should be:

longopts[LANG_COUNT + longopts_len] = (option_t){ NULL, 0, NULL, 0 };

Better yet, for Visual Studio compatibility, it could be rewritten as:

longopts[LANG_COUNT + longopts_len].name = NULL;
longopts[LANG_COUNT + longopts_len].has_arg = 0;
longopts[LANG_COUNT + longopts_len].flag = NULL;
longopts[LANG_COUNT + longopts_len].val = 0;

(see kjk@197105d for that and other VS fixes)

@kjk
Copy link

@kjk kjk commented on 04ec543 Oct 29, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also:

longopts = ag_malloc(sizeof(base_longopts) + sizeof(option_t) * (LANG_COUNT + 1));

i.e. need +1 element for the sentinel element being written to. Without this, valgrind --dsymutil=yes ./ag will complain about invalid memory writes and windows might crash (when doing malloc consistency checks).

See kjk@8db63a0

Please sign in to comment.