Skip to content

Instantly share code, notes, and snippets.

@artsi0m
Last active February 11, 2024 17:16
Show Gist options
  • Save artsi0m/b1e57caf905fdd514983315a9d98de49 to your computer and use it in GitHub Desktop.
Save artsi0m/b1e57caf905fdd514983315a9d98de49 to your computer and use it in GitHub Desktop.
Modified Tom Duff's com. (Original http://www.iq0.com/duffgram/com.c)
/*% cc -O0 -g % -o #
* com [-n] [file ...]
* looks for the sequence /*% in each file, and sends the rest of the
* line off to the shell, after replacing any instances of a `%' character
* with the filename, and any instances of `#' with the filename with its
* suffix removed. Used to allow information about how to compile a program
* to be stored with the program. The -n flag causes com not to
* act, but to print out the action it would have taken.
*
* This version of com would also create compile_flags.txt for clangd if
* -n flag is not specified.
*/
/* Copyright © 2022,2024 Artsiom Karakin
* Copyright © 2002-2011 Tom Duff
*
* See end of this file for LICENSE
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#define TWOPAGES 8192
#define BYTE unsigned char
int nflag=0;
int maxstat=0;
char command[TWOPAGES];
void make(char []);
int
main(int argc, char *argv[]){
int i;
FILE *comfile;
char str[TWOPAGES], *nl;
while(argc>1 && argv[1][0]=='-'){
for(i=1;argv[1][i];i++) switch(argv[1][i]){
case 'n': nflag++; break;
default:
Usage:
fprintf(stderr, "Usage: %s [-n] [file ...]\n", argv[0]);
exit(1);
}
argv++;
--argc;
}
if(argc==1){
if((comfile=fopen(".comfile", "r"))==NULL) goto Usage;
while(fgets(str, sizeof(str), comfile)!=NULL){
nl=strchr(str, '\n');
if(nl) *nl='\0';
make(str);
}
}
else{
if(!nflag && (comfile=fopen(".comfile", "w"))!=NULL){
for(i=1;i!=argc;i++) fprintf(comfile, "%s\n", argv[i]);
fclose(comfile);
}
for(i=1;i!=argc;i++){ make(argv[i]);}
}
exit(maxstat);
}
void make(char filename[]){
extern char command[];
char *s, *t, *suffix;
int c;
FILE *f;
int stat;
FILE *ccdb;
char *command_s;
char *command_o;
int command_i;
if((f=fopen(filename, "r"))==NULL){
warnx("%s", filename);
if(maxstat<1) maxstat=1;
return;
}
/*
* Look for /*%
*/
for(;;){
c=getc(f);
if(c==EOF){
warn("%s: no command\n", filename);
fclose(f);
if(maxstat<1) maxstat=1;
return;
}
if(c=='/'){
if((c=getc(f))=='*' && (c=getc(f))=='%') break;
ungetc(c, f); /* might be another slash! */
}
}
s=command;
do;while((c=getc(f))==' ' || c=='\t');
suffix=strrchr(filename, '.');
if(suffix==NULL) suffix=filename+strlen(filename);
while(c>=0 && c!='\n'){
switch(c){
default:
*s++=c;
break;
case '%':
c=getc(f);
if(c=='%') *s++='%';
else{
ungetc(c, f);
t=filename;
while(*t) *s++ = *t++;
}
break;
case '#':
c=getc(f);
if(c=='#') *s++='#';
else{
ungetc(c, f);
t=filename;
while(t!=suffix) *s++ = *t++;
}
}
c=getc(f);
}
*s='\0';
if(nflag){
printf("%s\n", command);
return;
}
fprintf(stderr, "%s\n", command);
switch(fork()){
case -1:
err(1, "%s\n", "can't fork");
case 0:
execl("/bin/sh", "sh", "-c", command, NULL);
err(1,"%s\n", "No shell!\n");
default:
wait(&stat);
if(stat>maxstat) maxstat=stat;
fclose(f);
}
if(!nflag){
if ((ccdb = fopen("compile_flags.txt", "w")) == NULL)
err(1, "%s\n", "can't open compile_flags.txt");
command_s = command;
command_i = 0;
while((command_o = strsep(&command_s," \t"))!= NULL){
if(command_i != 0)
fprintf(ccdb, "%s\n", command_o);
command_i++;
}
fclose(ccdb);
}
}
/*
* Copyright © 2022,2024 Artsiom Karakin
* Copyright © 2002-2011 Tom Duff
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in the
* Software without restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment