# C++2ltx.awk: C/C++ to LaTeX konvertor (version 22. 11. 1999) # c Petr Mikulik # Laboratory of Thin Films and Nanostructures # Masaryk University, Brno, Czech Republic # mikulik@physics.muni.cz, http://www.sci.muni.cz/~mikulik/ # This program is free (open source), but copyrighted and it must # be distributed with the whole accompanying stuff (see C++2ltx.zip) # Brief documentation: # -------------------- # Keywords in the file: # "//C++2ltx+" on a single line: all "//" and "/*" comments are taken as TeX enhanced # "//C++2ltx-" on a single line: all "//" and "/*" comments are taken as programmer's # comments (the default setting) # //+ and /*+ ... */ ... enhanced comments (supposed LaTeX code there) # //- and /*- ... */ ... usual C/C++ comment. This is useful when the # default setting are enhanced comments # //! ... this line is completely ignored # (in principle, equivalent to //- % blablabla) ### The program: BEGIN { END_quietly=0 cerr="/dev/stderr" # standard error output if (ARGC!=2) { print "\nScript C++2ltx.awk (c Petr Mikulik, Brno, August 1998)" >cerr print "Syntax: (g)awk -f C++2ltx.awk _input_C_or_C++_file_ >output_file.tex\n" >cerr print "This program is freeware distributed under GNU General Public License." >cerr print "Homepage: http://www.sci.muni.cz/~mikulik" >cerr END_quietly=1 exit # Remarks: # -- There can fit up to 65 characters "x" (in 10 pt) on line 250 mm width # (see CharsPerLine below) print "% Format: latex\n" print "\\documentclass[a4paper]{article}" print "\\special{landscape}" print "\\textwidth=274mm" print "\\oddsidemargin=-15.6mm" print "\\evensidemargin=-15.6mm" print "\\textheight=182.7mm" print "\\topmargin=-15.7mm" print "\n\\twocolumn \\columnsep=16mm \\columnseprule=1.0pt" print "\\parindent=0pt \\parskip=0pt" print "\\rightskip=0pt plus 0.3\\textwidth" print "\\hfuzz=1em \\vfuzz=1em" print "\n\\let\\Huge\\huge \\let\\huge\\LARGE \\let\\LARGE\\Large \\let\\Large\\large" print "\\let\\large\\normalsize \\let\\normalsize\\small \\let\\small\\footnotesize" print "\\let\\footnotesize\\scriptsize \\let\\scriptsize\\tiny" print "\\let\\bigskip\\medskip \\let\\medskip\\smallskip\n" print "\\usepackage{fancyhdr} \\pagestyle{fancy}" print "\\def\\headrulewidth{0pt} \\def\\footrulewidth{0pt} \\headsep=12pt" print "\\lhead{} \\rhead{} \\lfoot{} \\cfoot{} \\rfoot{}" print "\\chead{\\fboxrule=1.0pt \\framebox[\\hsize]{" "ls -l --full-time "ARGV[1] | getline # find the creation date of the file S=$3" "$4" "$5" "$7" "$6; close("ls -l --full-time "ARGV[1]) i=ARGV[1] gsub("_","\\_",i) # since \verb cannot be used in \chead, precede TeX's special gsub("\\$","\\$",i) # characters here if (index(i,"\\")) { # translation \ => $\backslash$ in the input filename gsub("\\\\","C2LTX",i) gsub("C2LTX","$\\backslash$",i) print " \\quad \\textbf{"i"} \\quad ("S") \\hfill" S=ENVIRON["LOGNAME"]; if (S=="") { S=ENVIRON["USER"]; if (S=="") S=root } S=S" from "ENVIRON["HOSTNAME"]" ("strftime("%a %b %d %Y %H:%M:%S",systime()) print " printed by "S") \\hfill Page \\thepage \\quad}}" print "\n\\usepackage{C++2ltx}" print "\\def\\up{\\unskip\\penalty0}" print "\\def\\CLTXVF{\\normalfont\\ttfamily\\slshape}" print "\n\\begin{document}\n" #### DEFAULT SETTINGS #### CharsPerLine=80 # limit for cutting the line into words (i.e. into the \hboxes) # depends on the default font and page size used---found manually DefaultEnhancedComment=0 # default enhanced comments yes/no #### END of the default setttings ### USUAL THINGS ### # cerr ... see above ### GLOBAL VARIABLES ### # separators for \verb command Separators=" |!+=-@;:.0123456789[]()" # the array of choosable separators Separator="" # separator chosen for the current line # line parsing Line ="" # contains the line read from input (should always equal $0) iLine =0 # index from which start or continue parsing of the Line isLongLine =0 # is this line long, i.e. are there more chars than CharsPerLine?? wasBlankLine=0 # flag for separating paragraphs by blank lines # comment treatment cPresent =0 # is there still a comment on the current line? c2slashes =0 # is it // or //+ comment? cEnhanced =0 # is it TeX-enhanced comment? cLeft =0; cRight =0 # parsing this piece of Line. If cOpen then cRight is unused cOpen =0 # set to 1 if the current line $0 is continuation of an open long /* comment cOpenFirstLine =0 # first line of open command opening cParIndentation =0 # string with \parindent and \hangindent to be employed at each beginning # new paragraph of an open enhanced comment #### END of global variables ##### ENDING THE PROGRAM ##### END { if (END_quietly); # write nothing since there is no (useful) output else print "\\end{document}" ####### PROCESS INPUT: Blank line and //C++2ltx + and - switches ####### NF==0 { # blank line if (cOpen && cEnhanced) printf "\n\n\\medskip" else print "\\medskip\n" wasBlankLine=1 next wasBlankLine!=0 { if (cOpen && cEnhanced) if (cParIndentation) printf cParIndentation wasBlankLine=0 $0=="//C++2ltx+" { DefaultEnhancedComment=1 next $0=="//C++2ltx-" { DefaultEnhancedComment=0 next $0 ~ "//!" { # line contains comment if (index($1,"//!")==1) next # ignore this line with only ignorable comment i=index($0,"//!") $0=substr($0,1,i-1) $0=StripTrailingSpaces($0) ################## MAIN PROGRAM PART ################## Line=$0; ExpandTabulators() iLine=1 # start parsing from the first column (of course) OutHead=""; OutLine="" # make the output strings empty if (!( cOpen && cEnhanced )) OutTail="" # keep still OutTail, i.e. \par} # Find a suitable \verb separator i=1; flag=1 while (flag) { Separator=substr(Separators,i,1); i++ flag=index(Line,Separator) if ( cOpen && cEnhanced ) isLongLine=0 else { isLongLine = (length(Line)>CharsPerLine) ? 1 : 0 ### RUDE OF HANGINDENT: if (isLongLine) { iLine=match(Line,"[^ ]") ParIndent=iLine-1 OutHead="{\\par\\leavevmode\\parindent="ParIndent*1.22"ex\\indent\\hangindent="(ParIndent+2)*1.22"ex" OutTail=OutTail "\\par}" } # Go over all pieces of code and comment until the whole line is processed while (iLine<=length(Line)) { FindNextComment() # find comment, and if it is there, then set its cXXXX staff if (!cPresent) { # there is no comment OutLine=OutLine VerbIt( substr(Line,iLine) ) iLine=length(Line)+1 else { # there is a COMMENT on the line if (iLine>CharsPerLine-15) # parbox too narrow, thus shorten hangindent OutLine=OutLine "\\advance\\hangindent-" 25*1.22 "ex" if (cLeft>iLine) # typeset the code (if exist) preceding the comment OutLine=OutLine VerbIt( substr(Line,iLine,cLeft-iLine) ) if (c2slashes || cOpen) { # It is // comment or long (open) /* comment. Format it now #! if (longComment...) if (cEnhanced) { # enhanced comment, no surrounding code needed OutLine=OutLine "\n" StripRoundSpaces(substr(Line,cLeft)) # isn't it the first thing on the line? if (cOpen && cLeft==match(Line,"[^ ]")-1) { # yes, it is, thus hangindent it cParIndentation="\\parindent="(cLeft-1)*1.22"ex\\indent\\hangindent="(cLeft-1)*1.22"ex%" OutHead="{" cParIndentation if (!cOpenFirstLine) OutLine="" # clear that "\verb| |" cOpenFirstLine=0 OutTail="\\par}" } else { # usual comment OutLine=OutLine "%\n{\\makeatletter\\let\\verbatim@font\\CLTXVF\\makeatother%\n" S=substr(Line,cLeft) if (isLongLine) S=StripLeadingSpaces(S) OutLine=OutLine VerbIt( S ) "\n}" iLine=length(Line)+1 else { # It is /* */ comment. Format it now if (cEnhanced) { # enhanced comment, no surrounding code needed OutLine=OutLine "\n" StripRoundSpaces(substr(Line,cLeft,cRight-cLeft-4)) "%\n" iLine=cRight-1 else { # usual comment OutLine=OutLine "%\n{\\makeatletter\\let\\verbatim@font\\CLTXVF\\makeatother%\n" OutLine=OutLine VerbIt( substr(Line,cLeft,cRight-cLeft+1) ) "}%\n" iLine=cRight+1 } } # the whole line has been processed # flush the output if (OutHead!="") printf "%s",OutHead if (OutLine!="") printf "%s",OutLine if (cOpen && cEnhanced) {} # printf "\n" else if (OutTail!="") { if (substr(OutLine,length(OutLine))!="\n") printf "\n" # print tail on a new line printf "%s",OutTail print "\n" } # end of the Main Program Part ####################### FUNCTIONS ####################### # This function expands tabulators in the global variable Line function ExpandTabulators ( i,S,sp ) { i=index(Line,"\t") if (i>0) { S="" while (i!=0) { S=S""substr(Line,1,i-1) sp=" " for (p=8-i%8; p>0; p--) sp=sp" " S=S""sp Line=substr(Line,i+1) i=index(Line,"\t") } Line=S""Line # Verboses a code passed from line. If the line is short, then put \verb in front of the line # enclosed by separators, otherwise makes hboxes of \verbed all words function VerbIt ( line, i,S ) { if (!isLongLine) { # print \verb++ return "\\verb"Separator line Separator # otherwise cut the line into \hbox{\verb++} while (length(line)>0) { i=match(line," [^ ]") if (i!=0) { # ending space S = S "\\hbox{\\verb" Separator substr(line,1,i) Separator "} \\up" line=substr(line,i+1); } else { S = S"\\hbox{\\verb" Separator line Separator "} " line = "" } return S # Is there comment? function FindNextComment ( line,S ) { if (cOpen) { # multiline comment /* ... */ continues cPresent=1 cLeft=1 cRight=index( substr(Line,1), "*/" ) cOpen = (cRight==0) ? 1:0 if (cRight>0) cRight += cEnhanced ? 3:1 return line=substr(Line,iLine) cPresent=indexNotInQuotes(line,"//") if (cPresent) { # there is // comment c2slashes=1 cLeft=cPresent+iLine-1 # position of the comment in Line # cRight is unused else { cPresent=indexNotInQuotes(line,"/*") if (!cPresent) return # there is no (more) comment on the current line c2slashes=0 # there is /* comment cLeft=cPresent+iLine-1 # position of the comment in Line cRight=index( substr(Line,cLeft+2), "*/" ) cOpen = (cRight==0) ? 1:0 if (cOpen) cOpenFirstLine=1 if (cRight>0) cRight+=cLeft+2 # find whether the comment is enhanced S=substr(line,cPresent+2,1) delSign=1 if (S=="-") cEnhanced=0; else # there was //- if (S=="+") cEnhanced=1; else # there was //+ { cEnhanced=DefaultEnhancedComment # use the default value delSign=0 } # no delete of sign # delete unnecessary parts of the comment: //+ and /*- (enhanced) or + and / for normal if (cEnhanced) Line=substr(Line,1,cLeft-1) substr(Line,cLeft+2+delSign) # delete also the // or /* else if (delSign) Line=substr(Line,1,cLeft+1) substr(Line,cLeft+3) function StripTrailingSpaces ( S ,i ) { i=match(S," +$") return (i==0) ? S : substr(S,1,i-1) function StripLeadingSpaces ( S ,i ) { i=match(S,"[^ ]") return (i==0) ? "" : substr(S,i) function StripRoundSpaces ( S ,i ) { i=match(S,"[^ ]") if (i==0) return "" S=substr(S,i) i=match(S," +$") return (i==0) ? S : substr(S,1,i-1) # This function works like index(S,pattern) with the exception that # the pattern cannot appear in quotes (inside C/C++ strings) function indexNotInQuotes ( S, pattern ) { offset=0 while (1) { p=index(substr(S,offset+1),pattern) if (p==0) return 0 # no pattern found p+=offset c=countQuotes(S,1,p-1) if (c%2==0) return p # even number of quotes, thus return the found position offset=p # returns number of quotes in the specified region. Takes care of \" function countQuotes ( S, from, to ) { S=substr(S,from,to) from=index(S,"\"") while (from) { # there is (still) a quote # increment counter of quotes if the quote is not backslashed: if (!( from>0 && substr(S,from-1,1)=="\\" )) c++ S=substr(S,from+1) from=index(S,"\"") return c # eof C++2ltx.awk