2017-09-14 17:48:41 +02:00
|
|
|
;;; C/C++
|
2016-10-14 14:03:30 +02:00
|
|
|
|
2017-09-14 17:48:41 +02:00
|
|
|
;;; TODO: Should we split this into mode-c and mode-c++?
|
2017-05-15 07:46:20 +02:00
|
|
|
|
2017-06-16 16:29:52 +02:00
|
|
|
(dolist (map (list c-mode-map c++-mode-map))
|
2018-02-13 13:42:11 +01:00
|
|
|
(ambrevar/define-keys map "C-c m" 'cc-main
|
2018-02-15 13:28:49 +01:00
|
|
|
"<f5>" 'ambrevar/cc-clean
|
2018-02-13 13:42:11 +01:00
|
|
|
"M-." 'semantic-ia-fast-jump
|
2018-11-09 08:36:40 +01:00
|
|
|
"C-c C-d" 'semantic-ia-show-doc
|
2018-02-13 13:42:11 +01:00
|
|
|
"M-<tab>" 'semantic-complete-analyze-inline)
|
2017-09-14 17:50:00 +02:00
|
|
|
(when (require 'company nil t)
|
2018-11-09 08:36:40 +01:00
|
|
|
(define-key map (kbd "M-<tab>") (if (require 'helm-company nil t) 'helm-company 'company-complete)))
|
|
|
|
(when (require 'gtk-look nil 'noerror)
|
|
|
|
(define-key map (kbd "C-c d") 'gtk-lookup-symbol)))
|
2017-06-16 21:33:53 +02:00
|
|
|
;; (define-key map (kbd "C-c o") 'ff-find-other-file)
|
2017-05-15 07:46:20 +02:00
|
|
|
|
2018-12-02 12:33:17 +01:00
|
|
|
(when (and (require 'gtk-look nil 'noerror)
|
|
|
|
(require 'w3m nil 'noerror))
|
|
|
|
;; Browse GTK documentation within Emacs.
|
|
|
|
;; TODO: Use eww instead of w3m. For some reason it hangs for almost a minute
|
|
|
|
;; with eww.
|
|
|
|
(add-to-list 'browse-url-browser-function '("file:///.*/gtk-doc/html/.*" . w3m-browse-url)))
|
|
|
|
|
2017-06-23 15:44:16 +02:00
|
|
|
(defvaralias 'c-basic-offset 'tab-width)
|
|
|
|
|
2017-06-16 21:33:53 +02:00
|
|
|
;;; C additional faces.
|
2017-06-16 21:01:02 +02:00
|
|
|
;;; Useless in quasi-monochrome.
|
|
|
|
;; (dolist (mode '(c-mode c++-mode))
|
|
|
|
;; (font-lock-add-keywords
|
|
|
|
;; mode
|
|
|
|
;; '(("\\<\\(and\\|or\\|not\\)\\>" . font-lock-keyword-face)
|
|
|
|
;; ;; Functions.
|
|
|
|
;; ("\\<\\(\\sw+\\)(" 1 'font-lock-function-name-face)
|
|
|
|
;; ("\\<\\(\\sw+\\)<\\sw+>(" 1 'font-lock-function-name-face))))
|
|
|
|
|
2018-02-15 13:28:49 +01:00
|
|
|
(defvar-local ambrevar/cc-ldlibs "-lm -pthread"
|
2017-05-11 19:38:01 +02:00
|
|
|
"Custom linker flags for C/C++ linkage.")
|
2013-06-12 23:40:20 +02:00
|
|
|
|
2018-02-15 13:28:49 +01:00
|
|
|
(defvar-local ambrevar/cc-ldflags ""
|
2017-05-11 19:38:01 +02:00
|
|
|
"Custom linker libs for C/C++ linkage.")
|
2013-06-12 23:40:20 +02:00
|
|
|
|
2018-02-15 13:28:49 +01:00
|
|
|
(defun ambrevar/cc-set-compiler (&optional nomakefile)
|
2014-03-24 19:33:33 +01:00
|
|
|
"Set compile command to be nearest Makefile or a generic command.
|
2014-02-21 20:22:20 +01:00
|
|
|
The Makefile is looked up in parent folders. If no Makefile is
|
2014-03-24 19:33:33 +01:00
|
|
|
found (or if NOMAKEFILE is non-nil or if function was called with
|
2017-09-14 17:48:41 +02:00
|
|
|
universal argument), then a configurable commandline is
|
|
|
|
provided."
|
2014-03-24 19:33:33 +01:00
|
|
|
(interactive "P")
|
2014-03-13 13:50:56 +01:00
|
|
|
(hack-local-variables)
|
2017-09-14 17:48:41 +02:00
|
|
|
;; Alternatively, if a Makefile is found, we could change default directory
|
|
|
|
;; and leave the compile command to "make". Changing `default-directory'
|
|
|
|
;; could have side effects though.
|
|
|
|
(let ((makefile-dir (locate-dominating-file "." "Makefile")))
|
|
|
|
(if (and makefile-dir (not nomakefile))
|
|
|
|
(setq compile-command (concat "make -k -C " (shell-quote-argument (file-name-directory makefile-dir))))
|
2017-05-12 08:34:17 +02:00
|
|
|
(setq compile-command
|
2017-05-28 12:32:48 +02:00
|
|
|
(let
|
|
|
|
((c++-p (eq major-mode 'c++-mode))
|
|
|
|
(file (file-name-nondirectory buffer-file-name)))
|
|
|
|
(format "%s %s -o '%s' %s %s %s"
|
|
|
|
(if c++-p
|
|
|
|
(or (getenv "CXX") "g++")
|
|
|
|
(or (getenv "CC") "gcc"))
|
|
|
|
(shell-quote-argument file)
|
|
|
|
(shell-quote-argument (file-name-sans-extension file))
|
|
|
|
(if c++-p
|
|
|
|
(or (getenv "CXXFLAGS") "-Wall -Wextra -Wshadow -DDEBUG=9 -g3 -O0")
|
|
|
|
(or (getenv "CFLAGS") "-ansi -pedantic -std=c11 -Wall -Wextra -Wshadow -DDEBUG=9 -g3 -O0"))
|
2018-02-15 13:28:49 +01:00
|
|
|
(or (getenv "LDFLAGS") ambrevar/cc-ldflags)
|
|
|
|
(or (getenv "LDLIBS") ambrevar/cc-ldlibs)))))))
|
2013-07-03 13:55:42 +02:00
|
|
|
|
2018-02-15 13:28:49 +01:00
|
|
|
(defun ambrevar/cc-clean ()
|
2013-07-06 20:02:05 +02:00
|
|
|
"Find Makefile and call the `clean' rule. If no Makefile is
|
2017-09-14 17:48:41 +02:00
|
|
|
found, no action is taken. The previous `compile' command is
|
2013-07-06 20:02:05 +02:00
|
|
|
restored."
|
|
|
|
(interactive)
|
2017-09-14 17:48:41 +02:00
|
|
|
(let (compile-command
|
|
|
|
(makefile-dir (locate-dominating-file "." "Makefile")))
|
|
|
|
(when makefile-dir
|
|
|
|
(compile (format "make -k -C %s clean" (shell-quote-argument makefile-dir))))))
|
2013-07-06 20:02:05 +02:00
|
|
|
|
2018-11-08 17:10:59 +01:00
|
|
|
(defun ambrevar/cc-force-compile ()
|
|
|
|
"If current `compile-command' is `make', force compilation.
|
|
|
|
This is done by appending the -B flag (--always-make) temporarily.
|
|
|
|
If the command is not `make', run it normally. "
|
|
|
|
(interactive)
|
|
|
|
(let ((compile-command compile-command))
|
|
|
|
(if (string-prefix-p "make " compile-command)
|
|
|
|
(compile (format "%s -B" compile-command))
|
|
|
|
(recompile))))
|
|
|
|
|
2018-11-17 14:01:29 +01:00
|
|
|
;; TODO: See https://github.com/koko1000ban/emacs-uncrustify-mode.
|
2018-11-12 16:58:16 +01:00
|
|
|
(defun ambrevar/cc-format-with-uncrustify (&optional cfg-file start end)
|
2016-06-12 22:48:36 +02:00
|
|
|
"Run uncrustify(1) on current buffer or region."
|
2018-11-12 16:58:16 +01:00
|
|
|
(interactive "f\nr")
|
|
|
|
(let (status
|
|
|
|
(start (or (and (region-active-p) start)
|
|
|
|
(point-min)))
|
|
|
|
(end (or (and (region-active-p) end)
|
|
|
|
(point-max)))
|
2018-11-17 14:01:29 +01:00
|
|
|
(formatbuf (get-buffer-create " *C format buffer*"))
|
|
|
|
(stderr (make-temp-file "uncrustify")))
|
2014-11-05 16:42:53 +01:00
|
|
|
(setq status
|
2018-11-17 14:01:29 +01:00
|
|
|
(call-process-region start end
|
|
|
|
"uncrustify"
|
|
|
|
nil (list formatbuf stderr) nil
|
|
|
|
;; "-lc" ; Uncrustify should be able to auto-detect.
|
|
|
|
"-c"
|
2018-11-08 12:35:54 +01:00
|
|
|
(or cfg-file
|
|
|
|
(expand-file-name ".uncrustify.cfg" (getenv "HOME")))))
|
2014-11-05 16:42:53 +01:00
|
|
|
(if (/= status 0)
|
2018-11-17 14:01:29 +01:00
|
|
|
(let ((error-message
|
|
|
|
(with-temp-buffer
|
|
|
|
(insert-file-contents-literally stderr)
|
|
|
|
(buffer-string))))
|
|
|
|
(delete-file stderr)
|
|
|
|
(kill-buffer formatbuf)
|
|
|
|
(error "error running uncrustify: %s" error-message))
|
|
|
|
(delete-file stderr)
|
|
|
|
(let ((old-line (line-number-at-pos))
|
|
|
|
(old-column (current-column))
|
|
|
|
(old-window-start-line (- (line-number-at-pos)
|
|
|
|
(line-number-at-pos (window-start)))))
|
2018-12-03 23:03:57 +01:00
|
|
|
(buffer-disable-undo)
|
2018-11-12 16:58:16 +01:00
|
|
|
(save-mark-and-excursion
|
|
|
|
(delete-region (or start (point-min)) (or end (point-max)))
|
|
|
|
(insert-buffer-substring formatbuf))
|
2018-11-17 14:01:29 +01:00
|
|
|
(goto-line old-line)
|
|
|
|
(move-to-column old-column)
|
2018-11-20 19:51:50 +01:00
|
|
|
(ignore-errors
|
|
|
|
;; recenter won't work if selected window is not the target buffer.
|
2018-12-03 23:03:57 +01:00
|
|
|
(recenter old-window-start-line))
|
|
|
|
(buffer-enable-undo))
|
2018-11-17 14:01:29 +01:00
|
|
|
(kill-buffer formatbuf)))
|
|
|
|
;; Return nil if in a `write-file-functions'.
|
|
|
|
nil)
|
2014-11-05 16:42:53 +01:00
|
|
|
|
2018-11-08 12:35:54 +01:00
|
|
|
(defun ambrevar/cc-format-file-lookup ()
|
|
|
|
"Find .clang-format or .uncrustify.cfg in parent folder up to Git root.
|
|
|
|
Return nil if non is found or if not a Git repository."
|
|
|
|
(unless (require 'magit nil 'noerror)
|
|
|
|
(error "Magit is missing"))
|
|
|
|
(when (or (magit-get-current-branch) (magit-get-current-tag))
|
|
|
|
(let ((git-root (magit-rev-parse "--show-toplevel"))
|
|
|
|
(default-directory default-directory))
|
|
|
|
(while (and (string= (magit-rev-parse "--show-toplevel") git-root)
|
|
|
|
(not (file-exists-p ".clang-format"))
|
|
|
|
(not (file-exists-p ".uncrustify.cfg")))
|
|
|
|
(cd ".."))
|
|
|
|
(or (and (file-exists-p ".clang-format")
|
|
|
|
(expand-file-name ".clang-format" default-directory))
|
|
|
|
(and (file-exists-p ".uncrustify.cfg")
|
|
|
|
(expand-file-name ".uncrustify.cfg" default-directory))))))
|
|
|
|
|
|
|
|
(defun ambrevar/cc-format ()
|
|
|
|
"Format C file.
|
|
|
|
It uses `ambrevar/cc-format-file-lookup' to find the format rules.
|
|
|
|
This is suitable for a `before-save-hook'."
|
|
|
|
(interactive)
|
|
|
|
(let ((cfg-file (ambrevar/cc-format-file-lookup)))
|
|
|
|
(cond
|
|
|
|
((and (string= (file-name-base cfg-file) ".clang-format")
|
|
|
|
(require 'clang-format nil 'noerror))
|
|
|
|
(clang-format-buffer))
|
2018-11-12 16:58:16 +01:00
|
|
|
((and (string= (file-name-base cfg-file) ".uncrustify")
|
2018-11-08 12:35:54 +01:00
|
|
|
(executable-find "uncrustify"))
|
|
|
|
(ambrevar/cc-format-with-uncrustify cfg-file)))))
|
|
|
|
|
|
|
|
(defun ambrevar/cc-turn-on-format ()
|
|
|
|
"Add `ambrevar/cc-format' to `before-save-hook' locally.
|
|
|
|
You can add your mode hook (e.g. `c-mode-hook')."
|
2018-11-17 14:01:29 +01:00
|
|
|
(add-hook 'write-file-functions 'ambrevar/cc-format nil 'local))
|
2018-11-08 12:35:54 +01:00
|
|
|
|
2017-08-14 16:36:27 +02:00
|
|
|
;;; GMP documentation
|
|
|
|
(with-eval-after-load "info-look"
|
|
|
|
(let ((mode-value (assoc 'c-mode (assoc 'symbol info-lookup-alist))))
|
|
|
|
(setcar (nthcdr 3 mode-value)
|
|
|
|
(cons '("(gmp)Function Index" nil "^ -.* " "\\>")
|
|
|
|
(nth 3 mode-value)))))
|
|
|
|
|
2016-10-14 14:32:46 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2017-05-28 12:32:48 +02:00
|
|
|
;;; Options
|
2016-06-12 22:48:36 +02:00
|
|
|
|
2018-05-10 11:39:03 +02:00
|
|
|
;; We don't want semantic in Scheme and others.
|
|
|
|
(setq semantic-new-buffer-setup-functions
|
|
|
|
'((c-mode . semantic-default-c-setup)
|
|
|
|
(c++-mode . semantic-default-c-setup)))
|
2018-02-15 13:28:49 +01:00
|
|
|
;;; Make sure Semanticdb folders is set before starting semantic.
|
2016-06-12 22:48:36 +02:00
|
|
|
(semantic-mode 1)
|
2018-11-08 17:26:21 +01:00
|
|
|
;; (global-semantic-stickyfunc-mode)
|
|
|
|
;; (global-semantic-decoration-mode)
|
|
|
|
;; Eldoc does not work but there is Semantic.
|
|
|
|
(global-semantic-idle-summary-mode)
|
|
|
|
|
|
|
|
;; Add support for some subdir-includes.
|
|
|
|
;; TODO: This could be automated by parsing `pkg-config --list-all` or maybe
|
|
|
|
;; `find -L . -maxdepth 1 -type d`.
|
|
|
|
(setq semantic-c-dependency-system-include-path
|
|
|
|
(append (mapcar (lambda (lib)
|
|
|
|
(expand-file-name
|
|
|
|
lib
|
|
|
|
(or (getenv "CPATH")
|
|
|
|
(if (file-directory-p (expand-file-name "~/.guix-profile/include"))
|
|
|
|
"~/.guix-profile/include"
|
|
|
|
"/usr/include"))))
|
|
|
|
'("glib-2.0" "gtk-3.0" "webkitgtk-4.0"))
|
|
|
|
'("/usr/include")))
|
2013-07-03 13:55:42 +02:00
|
|
|
|
2014-02-23 18:02:40 +01:00
|
|
|
(c-add-style
|
2015-07-11 12:33:45 +02:00
|
|
|
"ambrevar"
|
2014-10-26 18:04:11 +01:00
|
|
|
`((c-comment-only-line-offset . 0)
|
2014-10-31 13:06:26 +01:00
|
|
|
(c-auto-align-backslashes . nil)
|
|
|
|
(c-basic-offset . ,tab-width)
|
|
|
|
(c-offsets-alist
|
|
|
|
(arglist-cont-nonempty . +)
|
|
|
|
(arglist-intro . +)
|
|
|
|
(c . 0)
|
|
|
|
(case-label . 0)
|
|
|
|
(cpp-define-intro . 0)
|
2014-11-14 21:48:09 +01:00
|
|
|
(cpp-macro . 0)
|
2014-10-31 13:06:26 +01:00
|
|
|
(knr-argdecl-intro . 0)
|
|
|
|
(label . 0)
|
|
|
|
(statement-block-intro . +)
|
|
|
|
(statement-cont . +)
|
|
|
|
(substatement-label . 0)
|
2017-06-16 12:06:22 +02:00
|
|
|
(substatement-open . 0))))
|
|
|
|
(nconc c-default-style '((c-mode . "ambrevar") (c++-mode . "ambrevar")))
|
2014-02-22 19:13:19 +01:00
|
|
|
|
2017-05-28 12:32:48 +02:00
|
|
|
;;; Note that in Emacs 24, cc-mode calls its hooks manually in each mode init
|
|
|
|
;;; function. Since cc modes belong to prog-mode, each hook is called another
|
|
|
|
;;; time at the end of the initialization. No big deal since we only set some
|
|
|
|
;;; variables.
|
2017-05-22 16:24:25 +02:00
|
|
|
(dolist (hook '(c-mode-hook c++-mode-hook))
|
2017-05-28 12:03:28 +02:00
|
|
|
(when (require 'company nil t)
|
2017-06-16 16:29:52 +02:00
|
|
|
(add-hook hook 'company-mode))
|
2018-11-08 12:35:54 +01:00
|
|
|
(add-hook hook 'ambrevar/cc-turn-on-format)
|
2018-02-15 13:28:49 +01:00
|
|
|
(add-hook hook 'ambrevar/cc-set-compiler))
|
2013-06-12 23:40:20 +02:00
|
|
|
|
2016-10-14 14:32:46 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
2017-05-28 12:32:48 +02:00
|
|
|
;;; Skeletons
|
2014-02-20 14:06:47 +01:00
|
|
|
|
2017-05-28 12:32:48 +02:00
|
|
|
;;; Note that it is possible to extend the skel syntax with
|
|
|
|
;;; `skeleton-further-elements'. For instance:
|
|
|
|
; (setq skeleton-further-elements '((q "\"")))
|
2014-02-20 14:06:47 +01:00
|
|
|
|
2014-03-10 00:11:55 +01:00
|
|
|
(define-skeleton cc-debug
|
|
|
|
"Insert debug macros."
|
2014-02-13 15:56:13 +01:00
|
|
|
nil
|
2014-10-31 13:06:26 +01:00
|
|
|
> "#ifdef DEBUG
|
2014-03-10 00:11:55 +01:00
|
|
|
#define DEBUG_CMD(CMD) do {CMD;} while(0)
|
|
|
|
#else
|
|
|
|
#define DEBUG_CMD(CMD) do {} while(0)
|
|
|
|
#endif
|
|
|
|
|
2014-10-31 13:06:26 +01:00
|
|
|
"
|
|
|
|
'(insert-and-indent
|
2017-05-08 11:59:19 +02:00
|
|
|
"#define DEBUG_PRINT(...) DEBUG_CMD( \\
|
|
|
|
fprintf(stderr, \"%s:%d:\\t(%s)\\t\", __FILE__, __LINE__, __func__); \\
|
2014-10-31 13:06:26 +01:00
|
|
|
fprintf(stderr, __VA_ARGS__); \\
|
|
|
|
fprintf(stderr, \"\\n\"); \\
|
|
|
|
)"))
|
2014-02-13 15:56:13 +01:00
|
|
|
|
2014-03-20 13:09:50 +01:00
|
|
|
(define-skeleton cc-getopt
|
|
|
|
"Insert a getopt template."
|
|
|
|
nil
|
2014-10-31 13:06:26 +01:00
|
|
|
> "int opt;" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"while ((opt = getopt(argc, argv, \":hV\")) != -1) {" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"switch(opt) {" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"case 'h':" > \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"usage(argv[0]);" \n
|
|
|
|
"return 0;" \n
|
|
|
|
"case 'V':" > \n
|
|
|
|
"version();" \n
|
|
|
|
"return 0;" \n
|
|
|
|
"case ':':" > \n
|
|
|
|
"fprintf(stderr, \"ERROR: -%c needs an argument.\\nTry '%s -h' for more information.\\n\", optopt, argv[0]);" \n
|
|
|
|
"return EXIT_FAILURE;" \n
|
|
|
|
"case '?':" > \n
|
|
|
|
"fprintf(stderr, \"ERROR: Unknown argument %c.\\nTry '%s -h' for more information.\\n\", optopt, argv[0]);" \n
|
|
|
|
"return EXIT_FAILURE;" \n
|
|
|
|
"default:" > \n
|
|
|
|
"usage(argv[0]);" \n
|
|
|
|
"return EXIT_SUCCESS;" \n
|
|
|
|
"}" > \n
|
|
|
|
"}" > "\n" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"if (optind >= argc) {" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"fprintf(stderr, \"Expected argument after options\\n\");" \n
|
|
|
|
"exit(EXIT_FAILURE);" \n
|
|
|
|
"}" > \n)
|
2014-03-20 13:09:50 +01:00
|
|
|
|
2014-03-10 00:11:55 +01:00
|
|
|
(define-skeleton cc-loadfile
|
|
|
|
"Insert loadfile function."
|
|
|
|
nil
|
2014-11-14 21:48:09 +01:00
|
|
|
"unsigned long loadfile(const char *path, char **buffer_ptr) {" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"#define MAX_FILESIZE 1073741824 /* One gigabyte */" > "\n" \n
|
|
|
|
"/* Handle variable. */" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"char *buffer;" "\n" \n
|
|
|
|
"FILE *file = fopen(path, \"rb\");" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"if (file == NULL) {" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"perror(path);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"return 0;" \n
|
|
|
|
"}" > "\n" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"fseek(file, 0, SEEK_END);" \n
|
|
|
|
"long length = ftell(file);" \n
|
|
|
|
"/* fprintf(stdout, \"Note: file %s is %u bytes long.\\n\", path, length); */" "\n" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"if (length > MAX_FILESIZE) {" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"fprintf(stderr, \"%s size %ld is bigger than %d bytes.\\n\", path, length, MAX_FILESIZE);" \n
|
|
|
|
"fclose(file);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"return 0;" \n
|
|
|
|
"}" > "\n" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"fseek(file, 0, SEEK_SET);" \n
|
|
|
|
"buffer = (char *)malloc(length + 1);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"if (buffer == NULL) {" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"perror(\"malloc\");" \n
|
|
|
|
"fclose(file);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"return 0;" \n
|
|
|
|
"}" > "\n" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"if (fread(buffer, 1, length, file) == 0) {" \n
|
|
|
|
"fclose(file);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"return 0;" \n
|
|
|
|
"}" > "\n" \n
|
|
|
|
"buffer[length] = '\\0';" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"fclose(file);" "\n" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"*buffer_ptr = buffer;" \n
|
|
|
|
"return length;" \n
|
|
|
|
"}" > \n)
|
2014-03-10 00:11:55 +01:00
|
|
|
|
2014-02-20 14:06:47 +01:00
|
|
|
(define-skeleton cc-main
|
|
|
|
"Insert main function with basic includes."
|
|
|
|
nil
|
2014-03-20 13:09:50 +01:00
|
|
|
> "#include <inttypes.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
2014-02-20 14:06:47 +01:00
|
|
|
#include <stdio.h>
|
2014-03-20 13:09:50 +01:00
|
|
|
#include <stdlib.h>
|
2014-02-20 14:06:47 +01:00
|
|
|
#include <string.h>
|
2014-03-20 13:09:50 +01:00
|
|
|
#include <unistd.h>
|
2014-02-20 14:06:47 +01:00
|
|
|
|
2014-11-14 21:48:09 +01:00
|
|
|
int main(int argc, char **argv) {" \n
|
2018-11-17 14:01:29 +01:00
|
|
|
> @ _ \n
|
|
|
|
> "return 0;
|
2014-02-20 14:06:47 +01:00
|
|
|
}" \n)
|
|
|
|
|
2014-03-20 13:09:50 +01:00
|
|
|
(define-skeleton cc-usage-version
|
|
|
|
"Insert usage() and version() functions."
|
2014-10-31 13:06:26 +01:00
|
|
|
"Synopsis: "
|
|
|
|
> "static void usage(const char *executable) {" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"printf(\"Usage: %s [OPTIONS]\\n\\n\", executable);" \n
|
|
|
|
"puts(\"" str "\\n\");" "\n" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
|
2014-11-14 21:48:09 +01:00
|
|
|
"puts(\"Options:\");" \n
|
|
|
|
"puts(\" -h Print this help.\");" \n
|
|
|
|
"puts(\" -V Print version information.\");" "\n" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
|
2014-11-14 21:48:09 +01:00
|
|
|
"puts(\"\");" \n
|
|
|
|
"printf(\"See %s for more information.\\n\", MANPAGE);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"}" > "\n" \n
|
|
|
|
|
|
|
|
"static void version() {" \n
|
2014-11-14 21:48:09 +01:00
|
|
|
"printf(\"%s %s\\n\", APPNAME, VERSION);" \n
|
|
|
|
"printf(\"Copyright © %s %s\\n\", YEAR, AUTHOR);" \n
|
2014-10-31 13:06:26 +01:00
|
|
|
"}" > \n)
|
2014-03-20 13:09:50 +01:00
|
|
|
|
2017-06-18 18:50:31 +02:00
|
|
|
(provide 'init-cc)
|