├── .gdb_history ├── .gitignore ├── Makefile ├── README.md ├── config └── colors.h ├── documentation ├── BUGS ├── TODO ├── after.jpg ├── after.old.jpg ├── before.jpg ├── before.old.jpg ├── cscope.1.bz2 ├── csope.GIF ├── dev_man.md └── original_site_-_Cscope_Home_Page.html ├── object └── .placeholder ├── scripts ├── emacs.e ├── gmacs.ml └── ylwrap ├── source ├── auto_vararg.h ├── build.c ├── build.h ├── command.c ├── constants.h ├── crossref.c ├── dir.c ├── display.c ├── edit.c ├── egrep.h ├── egrep.y ├── exec.c ├── find.c ├── fscanner.l ├── global.h ├── gscope.c ├── help.c ├── help.h ├── input.c ├── invlib.c ├── invlib.h ├── keys.h ├── library.h ├── lookup.c ├── lookup.h ├── main.c ├── mouse.c ├── mypopen.c ├── opt.c ├── path.c ├── readline.c ├── refsfound.c ├── scanner.h ├── version.inc ├── vpath.c └── vpath.h └── test ├── CMDTEST_main.rb └── dummy_project ├── h.c ├── h.h └── main.c /.gdb_history: -------------------------------------------------------------------------------- 1 | b dispinit 2 | r 3 | n 4 | p first_col_width 5 | b display_frame 6 | c 7 | p first_col_width 8 | l 9 | d 1 10 | d 2 11 | wa first_col_width 12 | r 13 | r 14 | r 15 | help handle 16 | handle SIGINT stop 17 | r 18 | info signal-dispositions 19 | s 20 | start 21 | info signal-dispositions 22 | c 23 | where 24 | s 25 | where 26 | frame 0 27 | l 28 | b rl_complete 29 | c 30 | where 31 | c 32 | where 33 | l 34 | frame 0 35 | l 36 | info handle 37 | handle SIGINT pass 38 | n 39 | c 40 | l 41 | l screenmode_event_loop 42 | b handle_input 43 | c 44 | n 45 | n 46 | b siginit 47 | r 48 | n 49 | b wresult_input 50 | c 51 | n 52 | s 53 | n 54 | s 55 | n 56 | p editor 57 | p plusnum 58 | p file 59 | s 60 | n 61 | b wresult_input 62 | c 63 | n 64 | s 65 | n 66 | p refsfound 67 | p file 68 | p linenum 69 | b editref 70 | c 71 | n 72 | p i 73 | p topline 74 | b edit 75 | c 76 | where 77 | b input 78 | b handle_input 79 | c 80 | n 81 | n 82 | s 83 | n 84 | s 85 | n 86 | p i 87 | c 88 | c 89 | where 90 | frame 1 91 | where 92 | b handle_input 93 | c 94 | n 95 | p r 96 | n 97 | s 98 | n 99 | s 100 | p next_page_cursor 101 | p page_cursor 102 | p do_turn 103 | c 104 | d 1 105 | c 106 | where 107 | wa page_cursor 108 | wa page_cursor 109 | c 110 | l 111 | where 112 | l 113 | l 114 | where 115 | where 116 | l 117 | where 118 | p curdispline 119 | c 120 | p curdispline 121 | c 122 | p curdispline 123 | c 124 | p curdispline 125 | c 126 | c 127 | p curdispline 128 | p page_cursor 129 | c 130 | p page_cursor 131 | c 132 | r 133 | where 134 | frame 1 135 | p wtooltip 136 | r 137 | p tooltip_width 138 | b redisplay 139 | where 140 | l 141 | s 142 | where 143 | s 144 | n 145 | c 146 | c 147 | b redisplay 148 | c 149 | n 150 | where 151 | l 152 | c 153 | b redisplay 154 | c 155 | n 156 | n 157 | where 158 | finish 159 | finish 160 | finish 161 | s 162 | p c 163 | n 164 | b redisplay 165 | c 166 | n 167 | finish 168 | finish 169 | finish 170 | s 171 | n 172 | s 173 | n 174 | p EOF 175 | c 176 | where 177 | frame 11 178 | until 179 | where 180 | frame 9 181 | n 182 | frame 9 183 | finish 184 | where 185 | n 186 | s 187 | n 188 | s 189 | n 190 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.gch 3 | *.out 4 | csope 5 | source/lex.yy.c 6 | main.plist 7 | tmp-cmdtest-* 8 | .cmdtest-filter 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | LIBS:=ncurses readline 4 | 5 | CFLAGS += $(if $(SAN),-fsanitize=${SAN}) -Wno-unused-result 6 | CPPFLAGS:=-I config/ ${shell pkg-config --cflags ${LIBS}} 7 | LDLIBS=${shell pkg-config --libs ${LIBS}} 8 | LEX:=flex 9 | 10 | ifeq (${DEBUG}, 1) 11 | CFLAGS += -O0 -ggdb -Wall -Wpedantic 12 | else 13 | CFLAGS += -O3 -flto=auto -fomit-frame-pointer 14 | endif 15 | 16 | LEXD:=source/ 17 | LEXF:=$(shell find ${LEXD} -iname '*.l') 18 | GENLEX:=$(subst .l,.c,${LEXF}) 19 | 20 | YACCD:=source/ 21 | YACCF:=$(shell find ${YACCD} -iname '*.y') 22 | GENYACC:=$(subst .y,.c,${YACCF}) 23 | 24 | SRCD:=source/ 25 | OBJD:=object/ 26 | source:=$(shell find ${SRCD} -iname '*.c') ${GENLEX} ${GENYACC} 27 | object:=$(subst .c,.o,$(subst ${SRCD},${OBJD},${source})) 28 | 29 | OUTPUT:=csope 30 | 31 | main: ${object} 32 | ${LINK.c} ${object} -o ${OUTPUT} ${LDLIBS} 33 | 34 | object/%.o: source/%.c 35 | ${COMPILE.c} $< -o $@ 36 | 37 | source/%.c: source/%.l 38 | ${LEX} -o $@ $< 39 | 40 | source/%.c: source/%.y 41 | ${YACC} -o $@ $< 42 | 43 | install: ${OUTPUT} 44 | cp ${OUTPUT} /usr/bin/ 45 | 46 | clean: 47 | -${RM} ${GENLEX} 48 | -${RM} ${GENYACC} 49 | -${RM} ${object} 50 | -${RM} ${OUTPUT} 51 | 52 | test: 53 | cmdtest --fast 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Csope 2 | > C source code browser. 3 | > Fork of Cscope version 15.9, with various improvements. 4 | 5 | Because CScope is good and shall not be forgotten. 6 | While the original's maintenance seems abandoned and 7 | as far as I can tell you need a PhD in autoconf to compile the latest version, 8 | Csope is alive and well. 9 | 10 | ## Table of contents 11 | - [Demo](#demo) 12 | - [Features](#features) 13 | - [Interface](#interface) 14 | - [Usecases](#usecases) 15 | - [Improvements](#improvements) 16 | - [Installation](#installation) 17 | - [Gentoo](#gentoo) 18 | - [From source](#from-source) 19 | - [Quick start](#quick-start) 20 | - [Configuration](#Configuration) 21 | 22 | ## Demo 23 | ![demo](documentation/csope.GIF) 24 | 25 | ### Before/After 26 | #### After 27 | ![after](documentation/after.jpg) 28 | #### Before 29 | ![after](documentation/before.jpg) 30 | 31 | ## Features 32 | 33 | **Search for** 34 | + symbol 35 | + global definition 36 | + assignments to specified symbol 37 | + functions called by specified function 38 | + functions calling specified function 39 | + text string 40 | + egrep pattern 41 | + file 42 | + files #including specified file 43 | 44 | **...and open with your editor.** 45 | 46 | **Batch change search results _interactively_.** 47 | **Save/load/pipe results.** 48 | 49 | #### It fully supports: 50 | + C 51 | + Lex 52 | + Yacc 53 | #### Partially supports: 54 | + C++ 55 | + Java 56 | + Specification and Description Language 57 | 58 | ## Interface 59 | <-- Tab --> 60 | +--Version-----------------Case--+ +--------------------------------+ 61 | A |+--------------+---------------+| |+------------------------------+| 62 | | || Input Window | Result window || || || 63 | | |+--------------+ || ? || || 64 | || Mode Window | || ----> || Help || 65 | % || | || <---- || || 66 | || | || ... || || 67 | | || | || || || 68 | | || | || || || 69 | V |+--------------+---------------+| |+------------------------------+| 70 | +---------------------Tool Tips--+ +--------------------------------+ 71 | 72 | ## Usacases 73 | Csope shines at exploring stranger and obscure code bases due to its TUI. 74 | It sometimes gets mislabelled as a code navigation tool, 75 | but the original documentation describes it best as a "code browsing tool". 76 | Many tools can jump you to a definition or grep for patterns, 77 | but Csope is unique in that it allows for those and many other functionalities 78 | while providing you with a very comprehensible list of all results, 79 | ready to fire up your editor at just the spot. 80 | An example of its excellence is this project. The Cscope code-base used to be a total mess, 81 | fixing it would have been a lost cause, if not for Cscope itself. 82 | Well, Csope now. 83 | 84 | ## Improvements/Changes 85 | 86 | ## User side 87 | + Renamed the program, because "cscope" is annoying to type 88 | + Improved tui 89 | + GNU Readline/History integration 90 | ## To the code 91 | + Nuked autoconf, replaced with single Makefile 92 | + Reorganized the control flow 93 | + Encapsulated various functionalities 94 | + Removed macro hell used for compiling on a dead badgers 95 | + Reduced global state hell 96 | + Use stdbool instead of YES/NO macros 97 | + Removed dead code 98 | + ...and much more 99 | 100 | ## Installation 101 | 102 | ## Gentoo 103 | Add [my overlay](https://bis64wqhh3louusbd45iyj76kmn4rzw5ysawyan5bkxwyzihj67c5lid.onion/anon/agvxov-overlay.git) 104 | and install using portage. 105 | 106 | ## From source 107 | 108 | After you made sure you have the following installed: 109 | + ncurses 110 | + GNU Readline 111 | + GNU History (should come with Readline) 112 | + Lex (or GNU Flex) 113 | + Yacc (or GNU Bison) 114 | 115 | Just run: 116 | ```sh 117 | make 118 | ``` 119 | 120 | This will yield the executable "csope", which you are free to do whatever with. 121 | 122 | Hint: 123 | ```sh 124 | cp csope /usr/bin/ 125 | ``` 126 | 127 | ## Quick start 128 | Start browsing your project by running csope over it's source dir. 129 | 130 | ```sh 131 | csope -s source/ 132 | ``` 133 | 134 | ## Configuration 135 | 136 | ### Readline 137 | The readline integration should be complete -please let us know if not-, except for your prompt being used, which could easily break the TUIs display. 138 | 139 | The `rl_readline_name` variable will be set to "Csope", so you may have conditional configurations in your .inputrc with the following format: 140 | ``` 141 | $if Csope 142 | # 143 | $endif 144 | ``` 145 | 146 | ### Colors 147 | All can be configured sucklessly under "config/colors.h". Hopefully the comments are self evident. 148 | -------------------------------------------------------------------------------- /config/colors.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | /* List of color options: 5 | COLOR_BLACK 6 | COLOR_RED 7 | COLOR_GREEN 8 | COLOR_YELLOW 9 | COLOR_BLUE 10 | COLOR_MAGENTA 11 | COLOR_CYAN 12 | COLOR_WHITE 13 | -1 // for transparent (only works if that is your default terminal background) 14 | */ 15 | 16 | /* --- Valid presets --- */ 17 | #define MONOCHROME_PRESET 1 18 | #define COLORFUL_PRESET 2 19 | // Your own preset. 20 | // NOTE: you have to assign a color 21 | #define COLORFUL_CUSTOM 3 22 | 23 | /* --- Preset selection --- */ 24 | // Set to one of the numerical values above 25 | #define COLOR_PRESET 2 26 | 27 | #if COLOR_PRESET == 1 28 | # define COLOR_STD_FG COLOR_WHITE 29 | # define COLOR_STD_BG COLOR_BLACK 30 | # define COLOR_FRAME_FG COLOR_WHITE 31 | # define COLOR_FRAME_BG COLOR_BLACK 32 | # define COLOR_PROMPT_FG COLOR_WHITE 33 | # define COLOR_PROMPT_BG COLOR_BLACK 34 | # define COLOR_CURSOR COLOR_WHITE 35 | # define COLOR_FIELD_FG COLOR_WHITE 36 | # define COLOR_FIELD_BG COLOR_BLACK 37 | # define COLOR_FIELD_SELECTED_FG COLOR_WHITE 38 | # define COLOR_FIELD_SELECTED_BG COLOR_BLACK 39 | # define COLOR_HELP_FG COLOR_WHITE 40 | # define COLOR_HELP_BG COLOR_BLACK 41 | # define COLOR_TOOLTIP_FG COLOR_WHITE 42 | # define COLOR_TOOLTIP_BG COLOR_BLACK 43 | # define COLOR_CASE_FG COLOR_WHITE 44 | # define COLOR_CASE_BG COLOR_BLACK 45 | # define COLOR_MESSAGE_FG COLOR_WHITE 46 | # define COLOR_MESSAGE_BG COLOR_BLACK 47 | # define COLOR_PATTERN_FG COLOR_WHITE 48 | # define COLOR_PATTERN_BG COLOR_BLACK 49 | # define COLOR_TABLE_HEADER_FG COLOR_WHITE 50 | # define COLOR_TABLE_HEADER_BG COLOR_BLACK 51 | # define COLOR_TABLE_ID_FG COLOR_WHITE 52 | # define COLOR_TABLE_ID_BG COLOR_BLACK 53 | # define COLOR_TABLE_MARK_FG COLOR_WHITE 54 | # define COLOR_TABLE_MARK_BG COLOR_BLACK 55 | # define COLOR_TABLE_COL_FILE_FG COLOR_WHITE 56 | # define COLOR_TABLE_COL_FILE_BG COLOR_BLACK 57 | # define COLOR_TABLE_COL_FUNCTION_FG COLOR_WHITE 58 | # define COLOR_TABLE_COL_FUNCTION_BG COLOR_BLACK 59 | # define COLOR_TABLE_COL_LINE_FG COLOR_WHITE 60 | # define COLOR_TABLE_COL_LINE_BG COLOR_BLACK 61 | # define COLOR_TABLE_COL_TEXT_FG COLOR_WHITE 62 | # define COLOR_TABLE_COL_TEXT_BG COLOR_BLACK 63 | # define COLOR_TABLE_SELECTED_ID_FG COLOR_WHITE 64 | # define COLOR_TABLE_SELECTED_ID_BG COLOR_BLACK 65 | # define COLOR_TABLE_SELECTED_MARK_FG COLOR_WHITE 66 | # define COLOR_TABLE_SELECTED_MARK_BG COLOR_BLACK 67 | # define COLOR_TABLE_COL_SELECTED_FILE_FG COLOR_WHITE 68 | # define COLOR_TABLE_COL_SELECTED_FILE_BG COLOR_BLACK 69 | # define COLOR_TABLE_COL_SELECTED_FUNCTION_FG COLOR_WHITE 70 | # define COLOR_TABLE_COL_SELECTED_FUNCTION_BG COLOR_BLACK 71 | # define COLOR_TABLE_COL_SELECTED_LINE_FG COLOR_WHITE 72 | # define COLOR_TABLE_COL_SELECTED_LINE_BG COLOR_BLACK 73 | # define COLOR_TABLE_COL_SELECTED_TEXT_FG COLOR_WHITE 74 | # define COLOR_TABLE_COL_SELECTED_TEXT_BG COLOR_BLACK 75 | # define COLOR_PAGER_MSG_FG COLOR_WHITE 76 | # define COLOR_PAGER_MSG_BG COLOR_BLACK 77 | #elif COLOR_PRESET == 2 78 | # define COLOR_STD_FG COLOR_WHITE 79 | # define COLOR_STD_BG -1 80 | # define COLOR_FRAME_FG COLOR_GREEN 81 | # define COLOR_FRAME_BG -1 82 | # define COLOR_PROMPT_FG COLOR_BLUE 83 | # define COLOR_PROMPT_BG -1 84 | # define COLOR_CURSOR COLOR_WHITE 85 | # define COLOR_FIELD_FG COLOR_WHITE 86 | # define COLOR_FIELD_BG -1 87 | # define COLOR_FIELD_SELECTED_FG COLOR_BLACK 88 | # define COLOR_FIELD_SELECTED_BG COLOR_WHITE 89 | # define COLOR_HELP_FG COLOR_YELLOW 90 | # define COLOR_HELP_BG -1 91 | # define COLOR_TOOLTIP_FG COLOR_WHITE 92 | # define COLOR_TOOLTIP_BG COLOR_GREEN 93 | # define COLOR_CASE_FG COLOR_GREEN 94 | # define COLOR_CASE_BG -1 95 | # define COLOR_MESSAGE_FG COLOR_WHITE 96 | # define COLOR_MESSAGE_BG COLOR_BLACK 97 | # define COLOR_PATTERN_FG COLOR_WHITE 98 | # define COLOR_PATTERN_BG -1 99 | # define COLOR_TABLE_HEADER_FG COLOR_YELLOW 100 | # define COLOR_TABLE_HEADER_BG -1 101 | # define COLOR_TABLE_ID_FG COLOR_CYAN 102 | # define COLOR_TABLE_ID_BG -1 103 | # define COLOR_TABLE_MARK_FG COLOR_WHITE 104 | # define COLOR_TABLE_MARK_BG -1 105 | # define COLOR_TABLE_COL_FILE_FG COLOR_MAGENTA 106 | # define COLOR_TABLE_COL_FILE_BG -1 107 | # define COLOR_TABLE_COL_FUNCTION_FG COLOR_RED 108 | # define COLOR_TABLE_COL_FUNCTION_BG -1 109 | # define COLOR_TABLE_COL_LINE_FG COLOR_CYAN 110 | # define COLOR_TABLE_COL_LINE_BG -1 111 | # define COLOR_TABLE_COL_TEXT_FG COLOR_GREEN 112 | # define COLOR_TABLE_COL_TEXT_BG -1 113 | # define COLOR_TABLE_SELECTED_ID_FG COLOR_CYAN 114 | # define COLOR_TABLE_SELECTED_ID_BG COLOR_WHITE 115 | # define COLOR_TABLE_SELECTED_MARK_FG COLOR_BLACK 116 | # define COLOR_TABLE_SELECTED_MARK_BG COLOR_WHITE 117 | # define COLOR_TABLE_COL_SELECTED_FILE_FG COLOR_MAGENTA 118 | # define COLOR_TABLE_COL_SELECTED_FILE_BG COLOR_WHITE 119 | # define COLOR_TABLE_COL_SELECTED_FUNCTION_FG COLOR_RED 120 | # define COLOR_TABLE_COL_SELECTED_FUNCTION_BG COLOR_WHITE 121 | # define COLOR_TABLE_COL_SELECTED_LINE_FG COLOR_CYAN 122 | # define COLOR_TABLE_COL_SELECTED_LINE_BG COLOR_WHITE 123 | # define COLOR_TABLE_COL_SELECTED_TEXT_FG COLOR_GREEN 124 | # define COLOR_TABLE_COL_SELECTED_TEXT_BG COLOR_WHITE 125 | # define COLOR_PAGER_MSG_FG COLOR_YELLOW 126 | # define COLOR_PAGER_MSG_BG COLOR_WHITE 127 | #elif COLOR_PRESET == 3 128 | # define COLOR_STD_FG 129 | # define COLOR_STD_BG 130 | # define COLOR_FRAME_FG 131 | # define COLOR_FRAME_BG 132 | # define COLOR_PROMPT_FG 133 | # define COLOR_PROMPT_BG 134 | # define COLOR_CURSOR 135 | # define COLOR_FIELD_FG 136 | # define COLOR_FIELD_BG 137 | # define COLOR_FIELD_SELECTED_FG 138 | # define COLOR_FIELD_SELECTED_BG 139 | # define COLOR_HELP_FG 140 | # define COLOR_HELP_BG 141 | # define COLOR_TOOLTIP_FG 142 | # define COLOR_TOOLTIP_BG 143 | # define COLOR_CASE_FG 144 | # define COLOR_CASE_BG 145 | # define COLOR_MESSAGE_FG 146 | # define COLOR_MESSAGE_BG 147 | # define COLOR_PATTERN_FG 148 | # define COLOR_PATTERN_BG 149 | # define COLOR_TABLE_HEADER_FG 150 | # define COLOR_TABLE_HEADER_BG 151 | # define COLOR_TABLE_ID_FG 152 | # define COLOR_TABLE_ID_BG 153 | # define COLOR_TABLE_MARK_FG 154 | # define COLOR_TABLE_MARK_BG 155 | # define COLOR_TABLE_COL_FILE_FG 156 | # define COLOR_TABLE_COL_FILE_BG 157 | # define COLOR_TABLE_COL_FUNCTION_FG 158 | # define COLOR_TABLE_COL_FUNCTION_BG 159 | # define COLOR_TABLE_COL_LINE_FG 160 | # define COLOR_TABLE_COL_LINE_BG 161 | # define COLOR_TABLE_COL_TEXT_FG 162 | # define COLOR_TABLE_COL_TEXT_BG 163 | # define COLOR_TABLE_SELECTED_ID_FG 164 | # define COLOR_TABLE_SELECTED_ID_BG 165 | # define COLOR_TABLE_SELECTED_MARK_FG 166 | # define COLOR_TABLE_SELECTED_MARK_BG 167 | # define COLOR_TABLE_COL_SELECTED_FILE_FG 168 | # define COLOR_TABLE_COL_SELECTED_FILE_BG 169 | # define COLOR_TABLE_COL_SELECTED_FUNCTION_FG 170 | # define COLOR_TABLE_COL_SELECTED_FUNCTION_BG 171 | # define COLOR_TABLE_COL_SELECTED_LINE_FG 172 | # define COLOR_TABLE_COL_SELECTED_LINE_BG 173 | # define COLOR_TABLE_COL_SELECTED_TEXT_FG 174 | # define COLOR_TABLE_COL_SELECTED_TEXT_BG 175 | # define COLOR_PAGER_MSG_FG 176 | # define COLOR_PAGER_MSG_BG 177 | #else 178 | # error "Color profile not valid" 179 | #endif 180 | 181 | 182 | 183 | /* ############################################### */ 184 | /* ### Don't touch if you are just configuring ### */ 185 | enum color_pairs{ 186 | COLOR_PAIR_STD = 1, 187 | COLOR_PAIR_FRAME, 188 | COLOR_PAIR_PROMPT, 189 | COLOR_PAIR_FIELD, 190 | COLOR_PAIR_FIELD_SELECTED, 191 | COLOR_PAIR_HELP, 192 | COLOR_PAIR_TOOLTIP, 193 | COLOR_PAIR_CASE, 194 | COLOR_PAIR_PATTERN, 195 | COLOR_PAIR_MESSAGE, 196 | COLOR_PAIR_TABLE_HEADER, 197 | COLOR_PAIR_TABLE_ID, 198 | COLOR_PAIR_TABLE_MARK, 199 | COLOR_PAIR_TABLE_COL_FILE, 200 | COLOR_PAIR_TABLE_COL_FUNCTION, 201 | COLOR_PAIR_TABLE_COL_LINE, 202 | COLOR_PAIR_TABLE_COL_TEXT, 203 | COLOR_PAIR_TABLE_SELECTED_ID, 204 | COLOR_PAIR_TABLE_SELECTED_MARK, 205 | COLOR_PAIR_TABLE_COL_SELECTED_FILE, 206 | COLOR_PAIR_TABLE_COL_SELECTED_FUNCTION, 207 | COLOR_PAIR_TABLE_COL_SELECTED_LINE, 208 | COLOR_PAIR_TABLE_COL_SELECTED_TEXT, 209 | COLOR_PAIR_PAGER_MSG 210 | }; 211 | 212 | #define easy_init_pair(x) init_pair(COLOR_PAIR_ ## x, COLOR_ ## x ## _FG, COLOR_ ## x ## _BG) 213 | 214 | /* Other options: 215 | A_NORMAL : Normal display (no highlight) 216 | A_UNDERLINE : Underlining 217 | A_REVERSE : Reverse video 218 | A_BLINK : Blinking 219 | A_BOLD : Extra bright or bold 220 | A_STANDOUT : Best highlighting mode of the terminal. 221 | NOTE: you can specify more than one by separating the options by a '|' sign. 222 | { A_BLINK | A_BOLD } 223 | */ 224 | #define ATTRIBUTE_FIELD_SELECTED A_BOLD 225 | #define ATTRIBUTE_RESULT_SELECTED A_BOLD 226 | 227 | #endif 228 | -------------------------------------------------------------------------------- /documentation/BUGS: -------------------------------------------------------------------------------- 1 | > a space is inserted into the end of function head argument lists {`int f(void )`} 2 | 3 | > 14th December 2024 (yama): 4 | > Searching for symbol 'pp' (using 'Find assignments to this symbol' for e.g.) 5 | >will return search results for symbols named 'p', for example: 6 | > `p = malloc(sizeof(*p));` 7 | > 8 | > The symbol identifiers we return should match 'pp' exclusively, not 9 | >substrings. 10 | 11 | // No known bugs. 12 | -------------------------------------------------------------------------------- /documentation/TODO: -------------------------------------------------------------------------------- 1 | + what the hell is the deal with `source/gscope.c`? 2 | + sort out the global hell 3 | + sort out constants.h 4 | + lineflagafterfile is stupid 5 | + library.h...; "private library", in a program using 90 globals; ffs 6 | + scrollbar() uses magic int literals? 7 | + was there really ever a scrollbar? 8 | + a search struct could be great for caching and could ease the global situation 9 | + add support for ctags 10 | + add project summary page(?) 11 | + add basic search globbing 12 | + add search filters 13 | // From the original 14 | + Same capabilities as interactive in non interactive (one shot) mode 15 | + Provide some how-do-I-use-this-thing doc. 16 | -------------------------------------------------------------------------------- /documentation/after.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/documentation/after.jpg -------------------------------------------------------------------------------- /documentation/after.old.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/documentation/after.old.jpg -------------------------------------------------------------------------------- /documentation/before.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/documentation/before.jpg -------------------------------------------------------------------------------- /documentation/before.old.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/documentation/before.old.jpg -------------------------------------------------------------------------------- /documentation/cscope.1.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/documentation/cscope.1.bz2 -------------------------------------------------------------------------------- /documentation/csope.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/documentation/csope.GIF -------------------------------------------------------------------------------- /documentation/dev_man.md: -------------------------------------------------------------------------------- 1 | # Control flow 2 | ... 3 | 4 | # Project structure /*probably move to documentation*/ 5 | | Component | Purpose | 6 | | :-------: | :-----: | 7 | | main.c | generic init functions, main() and primary event loops (and junk) | 8 | | display.c | all functions directly dealing with NCurses | 9 | | input.c | top layer of functions dealing with user input; migth dispatch to readline | 10 | | opt.c | reads initialization options from cli/env | 11 | | find.c | searching functions | 12 | | readline.c | all functions directly dealing with GNU Readline; responsible for line editing in *input mode* | 13 | | help.c | all functions dealing with help messages | 14 | | auto\_vararg.h | vararg argument counter macro hack | 15 | | vpath.c | Make like VPATH support | 16 | | refsfound | XXX: ducktaping to page the cscope database | 17 | | build.c | XXX: functions required for building the cscope database | 18 | | globals.h | XXX: an inherited curse; global var/prototype hell | 19 | | command.c | XXX: clusterfuck | 20 | | mouse.c | XXX: legacy, non-functional (curses) mouse support 21 | 22 | # Key Symbols 23 | | Global | Role | 24 | | :----: | :--: | 25 | | int input_mode | Responsible of keeping track how current input should be handled. Not only does the readline handler depend on it, its also used to determine what types of inputs all legal (e.g. swapping to another window). Takes up on of the values of the INPUT_\* macros. 26 | | int window_change | Bit mask type of the CH_\* macros. Keeps track of the windows to be refresed on the next run of display(). Could be better utalized. 27 | 28 | # Notes 29 | CScope used to support something 30 | refered to as "OGS book and subsystem names". 31 | I have literally no clue what OGS is in reference to, 32 | it may or may not be the Quake II engine. 33 | Based on the code, 34 | the idea is that folders ending `.ss/` are "subsystems", 35 | and folders below subsystems are "books". 36 | CScope would display the subsystem and book names 37 | in its table view as any other field, 38 | given that the `ogs` global was set. 39 | So how do you set the ogs global? 40 | You don't, 41 | it was never documented, 42 | and there was never a way to set it at run time. 43 | I assume one project wanted it 44 | and sneaked in the patch. 45 | -------------------------------------------------------------------------------- /object/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agvxov/csope/15b43c126f96d723fe3dd39fe99121bc2d1d4eb5/object/.placeholder -------------------------------------------------------------------------------- /scripts/emacs.e: -------------------------------------------------------------------------------- 1 | / ========================================================================= / 2 | / Copyright (c) 1998-2000, The Santa Cruz Operation / 3 | / All rights reserved./ 4 | / / 5 | / Redistribution and use in source and binary forms, with or without/ 6 | / modification, are permitted provided that the following conditions are met:/ 7 | // 8 | / *Redistributions of source code must retain the above copyright notice,/ 9 | / this list of conditions and the following disclaimer./ 10 | // 11 | / *Redistributions in binary form must reproduce the above copyright notice,/ 12 | / this list of conditions and the following disclaimer in the documentation/ 13 | / and/or other materials provided with the distribution./ 14 | // 15 | / *Neither name of The Santa Cruz Operation nor the names of its contributors/ 16 | / may be used to endorse or promote products derived from this software/ 17 | / without specific prior written permission. / 18 | // 19 | / THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS/ 20 | / IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,/ 21 | / THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR/ 22 | / PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE/ 23 | / LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR/ 24 | / CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF/ 25 | / SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS/ 26 | / INTERRUPTION)/ 27 | / HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT/ 28 | / LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY/ 29 | / OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH/ 30 | / DAMAGE. / 31 | / ========================================================================= / 32 | 33 | / emacs menu for cscope / 34 | ((X) cscope (find current word [MACRO]) 35 | (extern symbol-character) 36 | 37 | / if this character is not part of a symbol / 38 | (cond ((not symbol-character) 39 | 40 | / if the previous character is not part of a symbol, go to 41 | the next word / 42 | back 43 | (cond ((not symbol-character) forward-word back-word)) 44 | )) 45 | / get the current symbol (leave cursor at beginning of symbol) / 46 | (while symbol-character forward) / go past last symbol character / 47 | mark / mark this point / 48 | back / back to last symbol character / 49 | (while (cond (symbol-character (return back)))) / back fails at BOF / 50 | (cond ((not symbol-character) forward)) / forward if not at BOF / 51 | pickup-region / get the symbol / 52 | (local-string symbol) 53 | symbol= 54 | 55 | / if arg > 0 then display the menu / 56 | (cond ((> arg 0) (display-menu 57 | (format symbol "5 Find functions calling %l()") 58 | (format symbol "4 Find functions called by %l()") 59 | (format symbol "3 Find global definition of %l") 60 | (format symbol "2 Find symbol %l") 61 | "1 Call cscope" 62 | 5) 63 | )) 64 | / get the selection / 65 | (local selection) 66 | (selection= (read-character "Selection?")) 67 | 68 | / if the selection is in range / 69 | (cond ((&& (>= selection '1') (<= selection '5')) 70 | 71 | / if the selection requests finding the symbol / 72 | (local-string findsymbol) 73 | (findsymbol= "") 74 | (cond ((>= selection '2') 75 | (findsymbol= (format (char-to-string (- selection 2)) symbol "-%l '%l'")))) 76 | 77 | / if arg > 1 or < 0 then don't update the cross-reference database / 78 | (local-string doption) 79 | (doption= "") 80 | (cond ((|| (> arg 1) (< arg 0)) (doption= "-d"))) 81 | 82 | / call cscope with usilent mode off / 83 | (local oldmode) / save old usilent mode / 84 | (oldmode= (set-mode "usilent" 0)) / turn off usilent mode / 85 | (run-command (format doption findsymbol "cscope %l %l")) 86 | (set-mode "usilent" oldmode) / restore usilent mode / 87 | )) 88 | ) 89 | / see if the current character is part of a symbol / 90 | (symbol-character () 91 | (local c) 92 | (c= current-character) 93 | (return (cond ((&& (>= c 'a') (<= c 'z'))) 94 | ((&& (>= c 'A') (<= c 'Z'))) 95 | ((&& (>= c '0') (<= c '9'))) 96 | ((== c '_')) 97 | ) 98 | ) 99 | ) 100 | -------------------------------------------------------------------------------- /scripts/gmacs.ml: -------------------------------------------------------------------------------- 1 | ; =========================================================================== 2 | ; Copyright (c) 1998-2000, The Santa Cruz Operation 3 | ; All rights reserved. 4 | 5 | ; Redistribution and use in source and binary forms, with or without 6 | ; modification, are permitted provided that the following conditions are met: 7 | 8 | ; *Redistributions of source code must retain the above copyright notice, 9 | ; this list of conditions and the following disclaimer. 10 | 11 | ; *Redistributions in binary form must reproduce the above copyright notice, 12 | ; this list of conditions and the following disclaimer in the documentation 13 | ; and/or other materials provided with the distribution. 14 | 15 | ; *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | ; may be used to endorse or promote products derived from this software 17 | ; without specific prior written permission. 18 | 19 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | ; IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | ; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | ; INTERRUPTION) 27 | ; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | ; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | ; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | ; DAMAGE. 31 | ; ========================================================================= 32 | 33 | ; cscope.ml (s.cscope.ml) - 1.4 (2/21/84 14:53:58) 34 | ; 35 | ; Macro to handle invocation of gmacs by cscope from the 36 | ; experimental tools. Cscope invokes gmacs with two arguments: 37 | ; 38 | ; gmacs +line file 39 | ; 40 | ; This macro gobbles the line number, visits the specified file, 41 | ; and moves to the specified line number. 42 | 43 | (progn 44 | args 45 | pluses 46 | (setq pluses 0) 47 | (setq args (argc)) 48 | (if (> args 1) 49 | (progn 50 | (if (= (string-to-char "+") (string-to-char (argv 1))) 51 | (setq pluses 1) 52 | ) 53 | (setq args (- args 1)) 54 | (while (> args pluses) 55 | (visit-file (argv args)) 56 | (setq args (- args 1)) 57 | ) 58 | (if (= (> (argc) 2) (> pluses 0)) 59 | (goto-line (argv 1)) 60 | ) 61 | ) 62 | ) 63 | ) 64 | -------------------------------------------------------------------------------- /scripts/ylwrap: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # ylwrap - wrapper for lex/yacc invocations. 3 | 4 | scriptversion=2016-01-11.22; # UTC 5 | 6 | # Copyright (C) 1996-2017 Free Software Foundation, Inc. 7 | # 8 | # Written by Tom Tromey . 9 | # 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # This file is maintained in Automake, please report 29 | # bugs to or send patches to 30 | # . 31 | 32 | get_dirname () 33 | { 34 | case $1 in 35 | */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';; 36 | # Otherwise, we want the empty string (not "."). 37 | esac 38 | } 39 | 40 | # guard FILE 41 | # ---------- 42 | # The CPP macro used to guard inclusion of FILE. 43 | guard () 44 | { 45 | printf '%s\n' "$1" \ 46 | | sed \ 47 | -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ 48 | -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \ 49 | -e 's/__*/_/g' 50 | } 51 | 52 | # quote_for_sed [STRING] 53 | # ---------------------- 54 | # Return STRING (or stdin) quoted to be used as a sed pattern. 55 | quote_for_sed () 56 | { 57 | case $# in 58 | 0) cat;; 59 | 1) printf '%s\n' "$1";; 60 | esac \ 61 | | sed -e 's|[][\\.*]|\\&|g' 62 | } 63 | 64 | case "$1" in 65 | '') 66 | echo "$0: No files given. Try '$0 --help' for more information." 1>&2 67 | exit 1 68 | ;; 69 | --basedir) 70 | basedir=$2 71 | shift 2 72 | ;; 73 | -h|--h*) 74 | cat <<\EOF 75 | Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... 76 | 77 | Wrapper for lex/yacc invocations, renaming files as desired. 78 | 79 | INPUT is the input file 80 | OUTPUT is one file PROG generates 81 | DESIRED is the file we actually want instead of OUTPUT 82 | PROGRAM is program to run 83 | ARGS are passed to PROG 84 | 85 | Any number of OUTPUT,DESIRED pairs may be used. 86 | 87 | Report bugs to . 88 | EOF 89 | exit $? 90 | ;; 91 | -v|--v*) 92 | echo "ylwrap $scriptversion" 93 | exit $? 94 | ;; 95 | esac 96 | 97 | 98 | # The input. 99 | input=$1 100 | shift 101 | # We'll later need for a correct munging of "#line" directives. 102 | input_sub_rx=`get_dirname "$input" | quote_for_sed` 103 | case $input in 104 | [\\/]* | ?:[\\/]*) 105 | # Absolute path; do nothing. 106 | ;; 107 | *) 108 | # Relative path. Make it absolute. 109 | input=`pwd`/$input 110 | ;; 111 | esac 112 | input_rx=`get_dirname "$input" | quote_for_sed` 113 | 114 | # Since DOS filename conventions don't allow two dots, 115 | # the DOS version of Bison writes out y_tab.c instead of y.tab.c 116 | # and y_tab.h instead of y.tab.h. Test to see if this is the case. 117 | y_tab_nodot=false 118 | if test -f y_tab.c || test -f y_tab.h; then 119 | y_tab_nodot=true 120 | fi 121 | 122 | # The parser itself, the first file, is the destination of the .y.c 123 | # rule in the Makefile. 124 | parser=$1 125 | 126 | # A sed program to s/FROM/TO/g for all the FROM/TO so that, for 127 | # instance, we rename #include "y.tab.h" into #include "parse.h" 128 | # during the conversion from y.tab.c to parse.c. 129 | sed_fix_filenames= 130 | 131 | # Also rename header guards, as Bison 2.7 for instance uses its header 132 | # guard in its implementation file. 133 | sed_fix_header_guards= 134 | 135 | while test $# -ne 0; do 136 | if test x"$1" = x"--"; then 137 | shift 138 | break 139 | fi 140 | from=$1 141 | # Handle y_tab.c and y_tab.h output by DOS 142 | if $y_tab_nodot; then 143 | case $from in 144 | "y.tab.c") from=y_tab.c;; 145 | "y.tab.h") from=y_tab.h;; 146 | esac 147 | fi 148 | shift 149 | to=$1 150 | shift 151 | sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;" 152 | sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;" 153 | done 154 | 155 | # The program to run. 156 | prog=$1 157 | shift 158 | # Make any relative path in $prog absolute. 159 | case $prog in 160 | [\\/]* | ?:[\\/]*) ;; 161 | *[\\/]*) prog=`pwd`/$prog ;; 162 | esac 163 | 164 | dirname=ylwrap$$ 165 | do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret' 166 | trap "ret=129; $do_exit" 1 167 | trap "ret=130; $do_exit" 2 168 | trap "ret=141; $do_exit" 13 169 | trap "ret=143; $do_exit" 15 170 | mkdir $dirname || exit 1 171 | 172 | cd $dirname 173 | 174 | case $# in 175 | 0) "$prog" "$input" ;; 176 | *) "$prog" "$@" "$input" ;; 177 | esac 178 | ret=$? 179 | 180 | if test $ret -eq 0; then 181 | for from in * 182 | do 183 | to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"` 184 | if test -f "$from"; then 185 | # If $2 is an absolute path name, then just use that, 186 | # otherwise prepend '../'. 187 | case $to in 188 | [\\/]* | ?:[\\/]*) target=$to;; 189 | *) target=../$to;; 190 | esac 191 | 192 | # Do not overwrite unchanged header files to avoid useless 193 | # recompilations. Always update the parser itself: it is the 194 | # destination of the .y.c rule in the Makefile. Divert the 195 | # output of all other files to a temporary file so we can 196 | # compare them to existing versions. 197 | if test $from != $parser; then 198 | realtarget=$target 199 | target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'` 200 | fi 201 | 202 | # Munge "#line" or "#" directives. Don't let the resulting 203 | # debug information point at an absolute srcdir. Use the real 204 | # output file name, not yy.lex.c for instance. Adjust the 205 | # include guards too. 206 | sed -e "/^#/!b" \ 207 | -e "s|$input_rx|$input_sub_rx|" \ 208 | -e "$sed_fix_filenames" \ 209 | -e "$sed_fix_header_guards" \ 210 | "$from" >"$target" || ret=$? 211 | 212 | # Check whether files must be updated. 213 | if test "$from" != "$parser"; then 214 | if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then 215 | echo "$to is unchanged" 216 | rm -f "$target" 217 | else 218 | echo "updating $to" 219 | mv -f "$target" "$realtarget" 220 | fi 221 | fi 222 | else 223 | # A missing file is only an error for the parser. This is a 224 | # blatant hack to let us support using "yacc -d". If -d is not 225 | # specified, don't fail when the header file is "missing". 226 | if test "$from" = "$parser"; then 227 | ret=1 228 | fi 229 | fi 230 | done 231 | fi 232 | 233 | # Remove the directory. 234 | cd .. 235 | rm -rf $dirname 236 | 237 | exit $ret 238 | 239 | # Local Variables: 240 | # mode: shell-script 241 | # sh-indentation: 2 242 | # eval: (add-hook 'write-file-hooks 'time-stamp) 243 | # time-stamp-start: "scriptversion=" 244 | # time-stamp-format: "%:y-%02m-%02d.%02H" 245 | # time-stamp-time-zone: "UTC0" 246 | # time-stamp-end: "; # UTC" 247 | # End: 248 | -------------------------------------------------------------------------------- /source/auto_vararg.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTO_VARARG 2 | #define AUTO_VARARG 3 | 4 | /* The following horrid macros can be used 5 | * to create vararg function which do not 6 | * require the developer to pass in the 7 | * argument count by hand. 8 | */ 9 | 10 | // useless without it, so might as well include 11 | #include 12 | 13 | #define PP_NARG(...) PP_NARG_(__VA_ARGS__, PP_RSEQ_N()) 14 | #define PP_NARG_(...) PP_128TH_ARG(__VA_ARGS__) 15 | #define PP_128TH_ARG( \ 16 | _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 17 | _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 18 | _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 19 | _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 20 | _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 21 | _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 22 | _61,_62,_63,_64,_65,_66,_67,_68,_69,_70, \ 23 | _71,_72,_73,_74,_75,_76,_77,_78,_79,_80, \ 24 | _81,_82,_83,_84,_85,_86,_87,_88,_89,_90, \ 25 | _91,_92,_93,_94,_95,_96,_97,_98,_99,_100, \ 26 | _101,_102,_103,_104,_105,_106,_107,_108,_109,_110, \ 27 | _111,_112,_113,_114,_115,_116,_117,_118,_119,_120, \ 28 | _121,_122,_123,_124,_125,_126,_127,N,...) N 29 | #define PP_RSEQ_N() \ 30 | 127,126,125,124,123,122,121,120, \ 31 | 119,118,117,116,115,114,113,112,111,110, \ 32 | 109,108,107,106,105,104,103,102,101,100, \ 33 | 99,98,97,96,95,94,93,92,91,90, \ 34 | 89,88,87,86,85,84,83,82,81,80, \ 35 | 79,78,77,76,75,74,73,72,71,70, \ 36 | 69,68,67,66,65,64,63,62,61,60, \ 37 | 59,58,57,56,55,54,53,52,51,50, \ 38 | 49,48,47,46,45,44,43,42,41,40, \ 39 | 39,38,37,36,35,34,33,32,31,30, \ 40 | 29,28,27,26,25,24,23,22,21,20, \ 41 | 19,18,17,16,15,14,13,12,11,10, \ 42 | 9,8,7,6,5,4,3,2,1,0 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /source/build.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 2001, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | #ifndef CSCOPE_BUILD_H 34 | #define CSCOPE_BUILD_H 35 | 36 | #include "global.h" /* FIXME: temp. only */ 37 | #include "invlib.h" 38 | 39 | /* types and macros of build.c to be used by other modules */ 40 | 41 | /* database output macros that update its offset */ 42 | #define dbputc(c) (++dboffset, (void)putc(c, newrefs)) 43 | #define dbfputs(s) (dboffset += strlen(s), fputs(s, newrefs)) 44 | 45 | /* declarations for globals defined in build.c */ 46 | 47 | extern bool buildonly; /* only build the database */ 48 | extern bool unconditional; /* unconditionally build database */ 49 | extern bool fileschanged; /* assume some files changed */ 50 | 51 | extern char *reffile; /* cross-reference file path name */ 52 | extern char *invname; /* inverted index to the database */ 53 | extern char *invpost; /* inverted index postings */ 54 | extern char *newreffile; /* new cross-reference file name */ 55 | extern FILE *newrefs; /* new cross-reference */ 56 | extern FILE *postings; /* new inverted index postings */ 57 | extern int symrefs; /* cross-reference file */ 58 | 59 | extern INVCONTROL invcontrol; /* inverted file control structure */ 60 | 61 | /* Prototypes of external functions defined by build.c */ 62 | 63 | void build(void); 64 | void free_newbuildfiles(void); 65 | void opendatabase(const char * const reffile); 66 | void rebuild(void); 67 | void setup_build_filenames(const char * const reffile); 68 | void seek_to_trailer(FILE *f); 69 | 70 | #endif /* CSCOPE_BUILD_H */ 71 | -------------------------------------------------------------------------------- /source/command.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol or text cross-reference 34 | * 35 | * command functions 36 | */ 37 | 38 | #include "global.h" 39 | #include "build.h" /* for rebuild() */ 40 | 41 | 42 | #include 43 | #include 44 | #include 45 | 46 | /* These are strictly used to test how keys are suppose to behave. 47 | * Think of it as modes: in _input mode_ the up arrow interacts 48 | * with the history, while in _mode mode_ it selects what operation 49 | * to perform with the user input. 50 | * In the original version this was handled by 51 | * `int selecting // whether the (upper) symbol list is being browsed`. 52 | */ 53 | extern const void *const winput; 54 | extern const void *const wmode; 55 | extern const void *const wresult; 56 | extern const void *const *const current_window; 57 | 58 | bool caseless; /* ignore letter case when searching */ 59 | bool *change; /* change this line */ 60 | char newpat[PATLEN + 1]; /* new pattern */ 61 | 62 | /* read references from a file */ 63 | bool readrefs(char *filename) { 64 | FILE *file; 65 | int c; 66 | 67 | if((file = myfopen(filename, "r")) == NULL) { 68 | cannotopen(filename); 69 | return false; 70 | } 71 | if((c = getc(file)) == EOF) { /* if file is empty */ 72 | fclose(file); 73 | return false; 74 | } 75 | totallines = 0; 76 | disprefs = 0; 77 | nextline = 1; 78 | if(writerefsfound() == true) { 79 | putc(c, refsfound); 80 | while((c = getc(file)) != EOF) { 81 | putc(c, refsfound); 82 | } 83 | fclose(file); 84 | fclose(refsfound); 85 | if((refsfound = myfopen(temp1, "rb")) == NULL) { 86 | cannotopen(temp1); 87 | return (false); 88 | } 89 | countrefs(); 90 | } else { 91 | fclose(file); 92 | } 93 | return (true); 94 | } 95 | 96 | /* count the references found */ 97 | void countrefs(void) { 98 | char file[PATHLEN + 1]; /* file name */ 99 | char function[PATLEN + 1]; /* function name */ 100 | char linenum[NUMLEN + 1]; /* line number */ 101 | int i; 102 | 103 | /* count the references found and find the length of the file, 104 | function, and line number display fields */ 105 | 106 | /* HBB NOTE 2012-04-07: it may look like we shouldn't assing tempstring here, 107 | * since it's not used. But it has to be assigned just so the return value 108 | * of fscanf will actually reach 4. */ 109 | while(EOF != (i = fscanf(refsfound, 110 | "%" PATHLEN_STR "s%" PATLEN_STR "s%" NUMLEN_STR 111 | "s %" TEMPSTRING_LEN_STR "[^\n]", 112 | file, 113 | function, 114 | linenum, 115 | tempstring))) { 116 | if((i != 4) || !isgraph((unsigned char)*file) || 117 | !isgraph((unsigned char)*function) || !isdigit((unsigned char)*linenum)) { 118 | postmsg("File does not have expected format"); 119 | totallines = 0; 120 | disprefs = 0; 121 | return; 122 | } 123 | if((i = strlen(pathcomponents(file, dispcomponents))) > filelen) { filelen = i; } 124 | if((i = strlen(function)) > fcnlen) { fcnlen = i; } 125 | if((i = strlen(linenum)) > numlen) { numlen = i; } 126 | ++totallines; 127 | } 128 | rewind(refsfound); 129 | 130 | /* restrict the width of displayed columns */ 131 | /* HBB FIXME 20060419: magic number alert! */ 132 | i = (COLS - 5) / 3; 133 | if(filelen > i && i > 4) { filelen = i; } 134 | if(fcnlen > i && i > 8) { fcnlen = i; } 135 | } 136 | -------------------------------------------------------------------------------- /source/constants.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * preprocessor macro and constant definitions 36 | */ 37 | 38 | #ifndef CSCOPE_CONSTANTS_H 39 | #define CSCOPE_CONSTANTS_H 40 | 41 | #define ctrl(x) (x & 037) /* control character macro */ 42 | 43 | /* fast string equality tests (avoids most strcmp() calls) */ 44 | #define strequal(s1, s2) (*(s1) == *(s2) && strcmp(s1, s2) == 0) 45 | #define strnotequal(s1, s2) (*(s1) != *(s2) || strcmp(s1, s2) != 0) 46 | 47 | /* set the mark character for searching the cross-reference file */ 48 | #define setmark(c) (blockmark = c, block[blocklen] = blockmark) 49 | 50 | /* get the next character in the cross-reference */ 51 | /* note that blockp is assumed not to be null */ 52 | #define getrefchar() \ 53 | (*(++blockp + 1) != '\0' ? *blockp : (read_crossreference_block() != NULL ? *blockp : '\0')) 54 | 55 | /* skip the next character in the cross-reference */ 56 | /* note that blockp is assumed not to be null and that 57 | this macro will always be in a statement by itself */ 58 | #define skiprefchar() \ 59 | if(*(++blockp + 1) == '\0') (void)read_crossreference_block() 60 | 61 | #define DUMMYCHAR ' ' /* use space as a dummy character */ 62 | #define MSGLEN ((PATLEN) + 80) /* displayed message length */ 63 | #define NUMLEN 10 /* line number length */ 64 | #define PATHLEN 250 /* file pathname length */ 65 | #define PATLEN 250 /* symbol pattern length */ 66 | #define TEMPSTRING_LEN 8191 /* max strlen() of the global temp string */ 67 | #define REFFILE "cscope.out" /* cross-reference output file */ 68 | #define NAMEFILE "cscope.files" /* default list-of-files file */ 69 | #define INVNAME "cscope.in.out" /* inverted index to the database */ 70 | #define INVPOST "cscope.po.out" /* inverted index postings */ 71 | #define INVNAME2 "cscope.out.in" /* follows correct naming convention */ 72 | #define INVPOST2 "cscope.out.po" /* follows correct naming convention */ 73 | 74 | #define STMTMAX 10000 /* maximum source statement length */ 75 | 76 | /* NOTE: _STRINGIZE ensures that if the argument is a macro, 77 | * its expanded before stringinization 78 | */ 79 | #define _STRINGIZE(x) #x 80 | #define STRINGIZE(x) _STRINGIZE(x) 81 | 82 | #define PATLEN_STR STRINGIZE(PATLEN) 83 | #define PATHLEN_STR STRINGIZE(PATHLEN) 84 | #define NUMLEN_STR STRINGIZE(NUMLEN) 85 | #define TEMPSTRING_LEN_STR STRINGIZE(TEMPSTRING_LEN) 86 | 87 | /* input fields (value matches field order on screen) */ 88 | enum { 89 | SYMBOL = 0, 90 | DEFINITION = 1, 91 | CALLEDBY = 2, 92 | CALLING = 3, 93 | STRING = 4, 94 | CHANGE = 5, 95 | REGEXP = 6, 96 | FILENAME = 7, 97 | INCLUDES = 8 98 | }; 99 | 100 | #define FIELDS 10 101 | 102 | /* file open modes */ 103 | #ifndef R_OK 104 | # define READ R_OK 105 | #else 106 | # define READ 4 107 | #endif 108 | 109 | #ifdef W_OK 110 | # define WRITE W_OK 111 | #else 112 | # define WRITE 2 113 | #endif 114 | 115 | #define O_TEXT 0x00 116 | #define O_BINARY 0x00 117 | 118 | /* Represents switch cases '0'...'9'. 119 | * Slightly hacky. 120 | * Should be use gcc/clang ranges? 121 | */ 122 | #define ASCII_DIGIT '0': \ 123 | case '1': \ 124 | case '2': \ 125 | case '3': \ 126 | case '4': \ 127 | case '5': \ 128 | case '6': \ 129 | case '7': \ 130 | case '8': \ 131 | case '9' 132 | 133 | #endif /* CSCOPE_CONSTANTS_H */ 134 | -------------------------------------------------------------------------------- /source/crossref.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | 34 | /* cscope - interactive C symbol cross-reference 35 | * 36 | * build cross-reference file 37 | */ 38 | 39 | #include "global.h" 40 | 41 | #include "build.h" 42 | #include "scanner.h" 43 | 44 | #include 45 | 46 | /* convert long to a string in base BASE notation */ 47 | #define ltobase(value) \ 48 | do { \ 49 | n = (value); \ 50 | s = buf + (sizeof(buf) - 1); \ 51 | *s = '\0'; \ 52 | digits = 1; \ 53 | while(n >= BASE) { \ 54 | ++digits; \ 55 | int i = n; \ 56 | n /= BASE; \ 57 | *--s = i - n * BASE + '!'; \ 58 | } \ 59 | *--s = n + '!'; \ 60 | } while(0) 61 | 62 | #define SYMBOLINC 20 /* symbol list size increment */ 63 | 64 | long dboffset; /* new database offset */ 65 | bool errorsfound; /* prompt before clearing messages */ 66 | long lineoffset; /* source line database offset */ 67 | long npostings; /* number of postings */ 68 | int nsrcoffset; /* number of file name database offsets */ 69 | long *srcoffset; /* source file name database offsets */ 70 | unsigned long symbols; /* number of symbols */ 71 | 72 | static char *filename; /* file name for warning messages */ 73 | static long fcnoffset; /* function name database offset */ 74 | static long macrooffset; /* macro name database offset */ 75 | static unsigned long msymbols = SYMBOLINC; /* maximum number of symbols */ 76 | 77 | typedef struct { /* symbol data */ 78 | int type; /* type */ 79 | unsigned int first; /* index of first character in text */ 80 | unsigned int last; /* index of last+1 character in text */ 81 | unsigned int length; /* symbol length */ 82 | unsigned int fcn_level; /* function level of the symbol */ 83 | } symbol_t; 84 | static symbol_t * symbol; 85 | 86 | static void putcrossref(void); 87 | static void savesymbol(int token, int num); 88 | 89 | void crossref(char * srcfile) { 90 | unsigned int length; /* symbol length */ 91 | unsigned int entry_no; /* function level of the symbol */ 92 | struct stat st; 93 | 94 | if(!((stat(srcfile, &st) == 0) && S_ISREG(st.st_mode))) { 95 | cannotopen(srcfile); 96 | errorsfound = true; 97 | return; 98 | } 99 | 100 | entry_no = 0; 101 | /* open the source file */ 102 | yyin = myfopen(srcfile, "r"); 103 | if(!yyin) { 104 | cannotopen(srcfile); 105 | errorsfound = true; 106 | return; 107 | } 108 | 109 | filename = srcfile; /* save the file name for warning messages */ 110 | putfilename(srcfile); /* output the file name */ 111 | dbputc('\n'); 112 | dbputc('\n'); 113 | 114 | /* read the source file */ 115 | initscanner(srcfile); 116 | fcnoffset = macrooffset = 0; 117 | symbols = 0; 118 | if(symbol == NULL) { symbol = malloc(msymbols * sizeof(*symbol)); } 119 | for(;;) { 120 | int token; /* current token */ 121 | /* get the next token */ 122 | switch(token = yylex()) { 123 | default: 124 | /* if requested, truncate C symbols */ 125 | length = last - first; 126 | if(trun_syms == true && length > 8 && token != INCLUDE && 127 | token != NEWFILE) { 128 | length = 8; 129 | last = first + 8; 130 | } 131 | /* see if the token has a symbol */ 132 | if(length == 0) { 133 | savesymbol(token, entry_no); 134 | break; 135 | } 136 | /* update entry_no if see function entry */ 137 | if(token == FCNDEF) { entry_no++; } 138 | /* see if the symbol is already in the list */ 139 | { 140 | unsigned i; 141 | for(i = 0; i < symbols; ++i) { 142 | if(length == symbol[i].length && 143 | strncmp(my_yytext + first, my_yytext + symbol[i].first, length) == 144 | 0 && 145 | entry_no == symbol[i].fcn_level && 146 | token == symbol[i].type) { /* could be a::a() */ 147 | break; 148 | } 149 | } 150 | if(i == symbols) { /* if not already in list */ 151 | savesymbol(token, entry_no); 152 | } 153 | } 154 | break; 155 | 156 | case NEWLINE: /* end of line containing symbols */ 157 | entry_no = 0; /* reset entry_no for each line */ 158 | #ifdef USING_LEX 159 | --yyleng; /* remove the newline */ 160 | #endif 161 | putcrossref(); /* output the symbols and source line */ 162 | lineno = myylineno; /* save the symbol line number */ 163 | #ifndef USING_LEX 164 | /* HBB 20010425: replaced yyleng-- by this chunk: */ 165 | if(my_yytext) *my_yytext = '\0'; 166 | my_yyleng = 0; 167 | #endif 168 | break; 169 | 170 | case LEXERR: /* Lexer error, abort further parsing of this file */ 171 | case LEXEOF: /* end of file; last line may not have \n */ 172 | 173 | /* if there were symbols, output them and the source line */ 174 | if(symbols > 0) { putcrossref(); } 175 | (void)fclose(yyin); /* close the source file */ 176 | 177 | /* output the leading tab expected by the next call */ 178 | dbputc('\t'); 179 | return; 180 | } 181 | } 182 | } 183 | 184 | /* save the symbol in the list */ 185 | static void savesymbol(int token, int num) { 186 | /* make sure there is room for the symbol */ 187 | if(symbols == msymbols) { 188 | msymbols += SYMBOLINC; 189 | symbol = realloc(symbol, msymbols * sizeof(*symbol)); 190 | } 191 | /* save the symbol */ 192 | symbol[symbols].type = token; 193 | symbol[symbols].first = first; 194 | symbol[symbols].last = last; 195 | symbol[symbols].length = last - first; 196 | symbol[symbols].fcn_level = num; 197 | ++symbols; 198 | } 199 | 200 | /* output the file name */ 201 | void putfilename(char *srcfile) { 202 | /* check for file system out of space */ 203 | /* note: dbputc is not used to avoid lint complaint */ 204 | if(putc(NEWFILE, newrefs) == EOF) { 205 | cannotwrite(newreffile); 206 | /* NOTREACHED */ 207 | } 208 | ++dboffset; 209 | if(invertedindex == true) { srcoffset[nsrcoffset++] = dboffset; } 210 | dbfputs(srcfile); 211 | fcnoffset = macrooffset = 0; 212 | } 213 | 214 | /* output the symbols and source line */ 215 | static 216 | void putcrossref(void) { 217 | unsigned int i, j; 218 | unsigned char c; 219 | bool blank; /* blank indicator */ 220 | unsigned int symput = 0; /* symbols output */ 221 | int type; 222 | 223 | /* output the source line */ 224 | lineoffset = dboffset; 225 | dboffset += fprintf(newrefs, "%d ", lineno); 226 | 227 | my_yytext[my_yyleng] = '\0'; 228 | 229 | blank = false; 230 | for(i = 0; i < my_yyleng; ++i) { 231 | 232 | /* change a tab to a blank and compress blanks */ 233 | if((c = my_yytext[i]) == ' ' || c == '\t') { 234 | blank = true; 235 | } else if(symput < symbols && i == symbol[symput].first) { 236 | /* look for the start of a symbol */ 237 | 238 | /* check for compressed blanks */ 239 | if(blank == true) { 240 | blank = false; 241 | dbputc(' '); 242 | } 243 | dbputc('\n'); /* symbols start on a new line */ 244 | 245 | /* output any symbol type */ 246 | if((type = symbol[symput].type) != IDENT) { 247 | dbputc('\t'); 248 | dbputc(type); 249 | } else { 250 | type = ' '; 251 | } 252 | /* output the symbol */ 253 | j = symbol[symput].last; 254 | c = my_yytext[j]; 255 | my_yytext[j] = '\0'; 256 | if(invertedindex == true) { putposting(my_yytext + i, type); } 257 | writestring(my_yytext + i); 258 | dbputc('\n'); 259 | my_yytext[j] = c; 260 | i = j - 1; 261 | ++symput; 262 | } else { 263 | /* HBB: try to save some time by early-out handling of 264 | * non-compressed mode */ 265 | if(compress == false) { 266 | if(blank == true) { 267 | dbputc(' '); 268 | blank = false; 269 | } 270 | j = i + strcspn(my_yytext + i, "\t "); 271 | if(symput < symbols && j >= symbol[symput].first) 272 | j = symbol[symput].first; 273 | c = my_yytext[j]; 274 | my_yytext[j] = '\0'; 275 | writestring(my_yytext + i); 276 | my_yytext[j] = c; 277 | i = j - 1; 278 | /* finished this 'i', continue with the blank */ 279 | continue; 280 | } 281 | 282 | /* check for compressed blanks */ 283 | if(blank == true) { 284 | if(dicode2[c]) { 285 | c = DICODE_COMPRESS(' ', c); 286 | } else { 287 | dbputc(' '); 288 | } 289 | } else if(IS_A_DICODE(c, my_yytext[i + 1]) && symput < symbols && 290 | i + 1 != symbol[symput].first) { 291 | /* compress digraphs */ 292 | c = DICODE_COMPRESS(c, my_yytext[i + 1]); 293 | ++i; 294 | } 295 | dbputc((int)c); 296 | blank = false; 297 | 298 | /* skip compressed characters */ 299 | if(c < ' ') { 300 | ++i; 301 | 302 | /* skip blanks before a preprocesor keyword */ 303 | /* note: don't use isspace() because \f and \v 304 | are used for keywords */ 305 | while((j = my_yytext[i]) == ' ' || j == '\t') { 306 | ++i; 307 | } 308 | /* skip the rest of the keyword */ 309 | while(isalpha((unsigned char)my_yytext[i])) { 310 | ++i; 311 | } 312 | /* skip space after certain keywords */ 313 | if(keyword[c].delim != '\0') { 314 | while((j = my_yytext[i]) == ' ' || j == '\t') { 315 | ++i; 316 | } 317 | } 318 | /* skip a '(' after certain keywords */ 319 | if(keyword[c].delim == '(' && my_yytext[i] == '(') { ++i; } 320 | --i; /* compensate for ++i in for() */ 321 | } /* if compressed char */ 322 | } /* else: not a symbol */ 323 | } /* for(i) */ 324 | 325 | /* ignore trailing blanks */ 326 | dbputc('\n'); 327 | dbputc('\n'); 328 | 329 | /* output any #define end marker */ 330 | /* note: must not be part of #define so putsource() doesn't discard it 331 | so findcalledbysub() can find it and return */ 332 | if(symput < symbols && symbol[symput].type == DEFINEEND) { 333 | dbputc('\t'); 334 | dbputc(DEFINEEND); 335 | dbputc('\n'); 336 | dbputc('\n'); /* mark beginning of next source line */ 337 | macrooffset = 0; 338 | } 339 | symbols = 0; 340 | } 341 | 342 | /* HBB 20000421: new function, for avoiding memory leaks */ 343 | /* free the cross reference symbol table */ 344 | void freecrossref() { 345 | if (symbol) { free(symbol); } 346 | symbol = NULL; 347 | symbols = 0; 348 | } 349 | 350 | /* output the inverted index posting */ 351 | void putposting(char *term, int type) { 352 | long n; 353 | char *s; 354 | int digits; /* digits output */ 355 | long offset; /* function/macro database offset */ 356 | char buf[11]; /* number buffer */ 357 | 358 | /* get the function or macro name offset */ 359 | offset = fcnoffset; 360 | if (macrooffset != 0) { offset = macrooffset; } 361 | /* then update them to avoid negative relative name offset */ 362 | switch (type) { 363 | case DEFINE: 364 | macrooffset = dboffset; 365 | break; 366 | case DEFINEEND: 367 | macrooffset = 0; 368 | return; /* null term */ 369 | case FCNDEF: 370 | fcnoffset = dboffset; 371 | break; 372 | case FCNEND: 373 | fcnoffset = 0; 374 | return; /* null term */ 375 | } 376 | /* ignore a null term caused by a enum/struct/union without a tag */ 377 | if (*term == '\0') { return; } 378 | /* skip any #include secondary type char (< or ") */ 379 | if (type == INCLUDE) { ++term; } 380 | /* output the posting, which should be as small as possible to reduce 381 | the temp file size and sort time */ 382 | (void)fputs(term, postings); 383 | (void)putc(' ', postings); 384 | 385 | /* the line offset is padded so postings for the same term will sort 386 | in ascending line offset order to order the references as they 387 | appear withing a source file */ 388 | ltobase(lineoffset); 389 | for (long i = PRECISION - digits; i > 0; --i) { 390 | (void)putc('!', postings); 391 | } 392 | do { 393 | (void)putc(*s, postings); 394 | } while(*++s != '\0'); 395 | 396 | /* postings are also sorted by type */ 397 | (void)putc(type, postings); 398 | 399 | /* function or macro name offset */ 400 | if (offset > 0) { 401 | (void)putc(' ', postings); 402 | ltobase(offset); 403 | do { 404 | (void)putc(*s, postings); 405 | } while(*++s != '\0'); 406 | } 407 | if (putc('\n', postings) == EOF) { 408 | cannotwrite(temp1); 409 | /* NOTREACHED */ 410 | } 411 | ++npostings; 412 | } 413 | 414 | /* put the string into the new database */ 415 | void writestring(char *s) { 416 | unsigned char c; 417 | 418 | if(compress == false) { 419 | /* Save some I/O overhead by using puts() instead of putc(): */ 420 | dbfputs(s); 421 | return; 422 | } 423 | /* compress digraphs */ 424 | for(int i = 0; (c = s[i]) != '\0'; ++i) { 425 | if(/* dicode1[c] && dicode2[(unsigned char) s[i + 1]] */ 426 | IS_A_DICODE(c, s[i + 1])) { 427 | /* c = (0200 - 2) + dicode1[c] + dicode2[(unsigned char) s[i + 1]]; */ 428 | c = DICODE_COMPRESS(c, s[i + 1]); 429 | ++i; 430 | } 431 | dbputc(c); 432 | } 433 | } 434 | 435 | /* print a warning message with the file name and line number */ 436 | void warning(char *text) { 437 | (void)fprintf(stderr, 438 | PROGRAM_NAME ": \"%s\", line %d: warning: %s\n", 439 | filename, 440 | myylineno, 441 | text 442 | ); 443 | errorsfound = true; 444 | } 445 | -------------------------------------------------------------------------------- /source/edit.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * file editing functions 36 | */ 37 | 38 | #include "global.h" 39 | #if defined(USE_NCURSES) && !defined(RENAMED_NCURSES) 40 | # include 41 | #else 42 | # include 43 | #endif 44 | 45 | /* edit this displayed reference */ 46 | 47 | void editref(int i) { 48 | char file[PATHLEN + 1]; /* file name */ 49 | char linenum[NUMLEN + 1]; /* line number */ 50 | 51 | /* verify that there is a references found file */ 52 | if(refsfound == NULL) { return; } 53 | /* get the selected line */ 54 | seekrelline(i); 55 | 56 | /* get the file name and line number */ 57 | if(fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s", file, linenum) == 2) { 58 | edit(file, linenum); 59 | } 60 | } 61 | 62 | /* edit all references */ 63 | 64 | void editall(void) { 65 | char file[PATHLEN + 1]; /* file name */ 66 | char linenum[NUMLEN + 1]; /* line number */ 67 | int c; 68 | 69 | /* verify that there is a references found file */ 70 | if(refsfound == NULL) { return; } 71 | /* get the first line */ 72 | fseek(refsfound, 0, SEEK_SET); 73 | 74 | /* get each file name and line number */ 75 | while( 76 | fscanf(refsfound, "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s%*[^\n]", file, linenum) == 77 | 2) { 78 | edit(file, linenum); /* edit it */ 79 | if(editallprompt == true) { 80 | addstr( 81 | "Type ^D to stop editing all lines, or any other character to continue: "); 82 | if((c = getch()) == EOF || c == ctrl('D') || c == ctrl('Z')) { break; } 83 | } 84 | } 85 | } 86 | 87 | /* call the editor */ 88 | void edit(const char *filename, const char *const linenum) { 89 | const char *const editor_basename = basename(editor); 90 | char msg[MSGLEN + 1]; /* message */ 91 | char plusnum[NUMLEN + 20]; /* line number option: allow space for wordy line# flag */ 92 | 93 | filename = prepend_path(prependpath, filename); 94 | snprintf(msg, sizeof(msg), "%s +%s %s", basename(editor), linenum, filename); 95 | postmsg(msg); 96 | snprintf(plusnum, sizeof(plusnum), lineflag, linenum); 97 | 98 | /* Some pagers will not start paging, unless the input 99 | * file has more lines thant the screen does. 100 | * The way to get them to pause, is to pass in /dev/null too, 101 | * imatating endless blank lines. 102 | */ 103 | const char *const shit_pagers[] = {"page", "more", NULL}; 104 | for(const char *const *sp = shit_pagers; *sp != NULL; sp++) { 105 | if(!strcmp(editor_basename, *sp)) { 106 | execute(editor, editor, plusnum, filename, "/dev/null", NULL); 107 | goto end; 108 | } 109 | } 110 | 111 | if(lineflagafterfile) { 112 | execute(editor, editor, filename, plusnum, NULL); 113 | } else { 114 | execute(editor, editor, plusnum, filename, NULL); 115 | } 116 | 117 | end: 118 | clear(); /* redisplay screen */ 119 | } 120 | 121 | /* if requested, prepend a path to a relative file name */ 122 | const char * prepend_path(const char * prepand_with, const char * file) { 123 | static char path[PATHLEN + 1]; // XXX 124 | 125 | if (!prepand_with 126 | || *file == '/') { 127 | return file; 128 | } 129 | 130 | snprintf(path, sizeof(path), "%s/%s", prependpath, file); 131 | return path; 132 | } 133 | -------------------------------------------------------------------------------- /source/egrep.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.8.2. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, 6 | Inc. 7 | 8 | This program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . */ 20 | 21 | /* As a special exception, you may create a larger work that contains 22 | part or all of the Bison parser skeleton and distribute that work 23 | under terms of your choice, so long as that work isn't itself a 24 | parser generator using the skeleton or a modified version thereof 25 | as a parser skeleton. Alternatively, if you modify or redistribute 26 | the parser skeleton itself, you may (at your option) remove this 27 | special exception, which will cause the skeleton and the resulting 28 | Bison output files to be licensed under the GNU General Public 29 | License without this special exception. 30 | 31 | This special exception was added by the Free Software Foundation in 32 | version 2.2 of Bison. */ 33 | 34 | /* DO falseT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, 35 | especially those whose name start with YY_ or yy_. They are 36 | private implementation details that can be changed or removed. */ 37 | 38 | #ifndef YY_YY_EGREP_H_INCLUDED 39 | #define YY_YY_EGREP_H_INCLUDED 40 | /* Debug traces. */ 41 | #ifndef YYDEBUG 42 | # define YYDEBUG 0 43 | #endif 44 | #if YYDEBUG 45 | extern int yydebug; 46 | #endif 47 | 48 | /* Token kinds. */ 49 | #ifndef YYTOKENTYPE 50 | # define YYTOKENTYPE 51 | 52 | enum yytokentype { 53 | YYEMPTY = -2, 54 | YYEOF = 0, /* "end of file" */ 55 | YYerror = 256, /* error */ 56 | YYUNDEF = 257, /* "invalid token" */ 57 | CHAR = 258, /* CHAR */ 58 | DOT = 259, /* DOT */ 59 | CCL = 260, /* CCL */ 60 | NCCL = 261, /* NCCL */ 61 | OR = 262, /* OR */ 62 | CAT = 263, /* CAT */ 63 | STAR = 264, /* STAR */ 64 | PLUS = 265, /* PLUS */ 65 | QUEST = 266 /* QUEST */ 66 | }; 67 | typedef enum yytokentype yytoken_kind_t; 68 | #endif 69 | /* Token kinds. */ 70 | #define YYEMPTY -2 71 | #define YYEOF 0 72 | #define YYerror 256 73 | #define YYUNDEF 257 74 | #define CHAR 258 75 | #define DOT 259 76 | #define CCL 260 77 | #define NCCL 261 78 | #define OR 262 79 | #define CAT 263 80 | #define STAR 264 81 | #define PLUS 265 82 | #define QUEST 266 83 | 84 | /* Value type. */ 85 | #if !defined YYSTYPE && !defined YYSTYPE_IS_DECLARED 86 | typedef int YYSTYPE; 87 | # define YYSTYPE_IS_TRIVIAL 1 88 | # define YYSTYPE_IS_DECLARED 1 89 | #endif 90 | 91 | 92 | extern YYSTYPE yylval; 93 | 94 | 95 | int yyparse(void); 96 | 97 | 98 | #endif /* !YY_YY_EGREP_H_INCLUDED */ 99 | -------------------------------------------------------------------------------- /source/egrep.y: -------------------------------------------------------------------------------- 1 | %{ 2 | /*=========================================================================== 3 | Copyright (c) 1998-2000, The Santa Cruz Operation 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | *Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | *Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | *Neither name of The Santa Cruz Operation nor the names of its contributors 17 | may be used to endorse or promote products derived from this software 18 | without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 21 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 22 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 24 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | DAMAGE. 32 | =========================================================================*/ 33 | 34 | /* 35 | * egrep -- find lines containing a regular expression 36 | */ 37 | %} 38 | 39 | %{ 40 | #include "global.h" 41 | #include 42 | #include 43 | 44 | #include /* jmp_buf */ 45 | 46 | #define nextch() (*input++) 47 | 48 | #define MAXLIN 350 49 | #define MAXPOS 4000 50 | #define NCHARS 256 51 | #define NSTATES 128 52 | #define FINAL -1 53 | static char gotofn[NSTATES][NCHARS]; 54 | static int state[NSTATES]; 55 | static char out[NSTATES]; 56 | static unsigned int line; 57 | static int name[MAXLIN]; 58 | static unsigned int left[MAXLIN]; 59 | static unsigned int right[MAXLIN]; 60 | static unsigned int parent[MAXLIN]; 61 | static int foll[MAXLIN]; 62 | static int positions[MAXPOS]; 63 | static char chars[MAXLIN]; 64 | static int nxtpos; 65 | static int nxtchar; 66 | static int tmpstat[MAXLIN]; 67 | static int initstat[MAXLIN]; 68 | static int xstate; 69 | static int count; 70 | static int icount; 71 | static char *input; 72 | static long lnum; 73 | static int iflag; 74 | static jmp_buf env; /* setjmp/longjmp buffer */ 75 | static char *message; /* error message */ 76 | 77 | /* Internal prototypes: */ 78 | static void cfoll(int v); 79 | static void cgotofn(void); 80 | static int cstate(int v); 81 | static int member(int symb, int set, int torf); 82 | static int notin(int n); 83 | static void syntax_error(void); 84 | static void table_overflow(void); 85 | static void add(int *array, int n); 86 | static void follow(unsigned int v); 87 | static int unary(int x, int d); 88 | static int node(int x, int l, int r); 89 | static unsigned int cclenter(int x); 90 | static unsigned int enter(int x); 91 | 92 | static int yylex(void); 93 | static int yyerror(char *); 94 | %} 95 | 96 | %token CHAR DOT CCL NCCL OR CAT STAR PLUS QUEST 97 | %left OR 98 | %left CHAR DOT CCL NCCL '(' 99 | %left CAT 100 | %left STAR PLUS QUEST 101 | 102 | %% 103 | pattern 104 | : t { 105 | unary(FINAL, $1); 106 | line--; 107 | } 108 | ; 109 | 110 | t 111 | : b r { 112 | $$ = node(CAT, $1, $2); 113 | } 114 | | OR b r OR { 115 | $$ = node(CAT, $2, $3); 116 | } 117 | | OR b r { 118 | $$ = node(CAT, $2, $3); 119 | } 120 | | b r OR { 121 | $$ = node(CAT, $1, $2); 122 | } 123 | ; 124 | 125 | b 126 | : { 127 | /* XXX: 128 | * why the fuck does this state exist? 129 | * what does it stand for? 130 | * can we enter it? do we always enter it? 131 | */ 132 | $$ = enter(DOT); 133 | $$ = unary(STAR, $$); 134 | } 135 | ; 136 | 137 | r 138 | : CHAR { 139 | $$ = enter($1); 140 | } 141 | | DOT { 142 | $$ = enter(DOT); 143 | } 144 | | CCL { 145 | $$ = cclenter(CCL); 146 | } 147 | | NCCL { 148 | $$ = cclenter(NCCL); 149 | } 150 | ; 151 | 152 | r 153 | : r OR r { 154 | $$ = node(OR, $1, $3); 155 | } 156 | | r r %prec CAT { 157 | $$ = node(CAT, $1, $2); 158 | } 159 | | r STAR { 160 | $$ = unary(STAR, $1); 161 | } 162 | | r PLUS { 163 | $$ = unary(PLUS, $1); 164 | } 165 | | r QUEST { 166 | $$ = unary(QUEST, $1); 167 | } 168 | | '(' r ')' { 169 | $$ = $2; 170 | } 171 | | error 172 | ; 173 | 174 | %% 175 | static 176 | int yyerror(char *s) { 177 | message = s; 178 | longjmp(env, 1); 179 | return 1; /* silence a warning */ 180 | } 181 | 182 | static 183 | int yylex(void) { 184 | int cclcnt, x; 185 | char c, d; 186 | 187 | switch(c = nextch()) { 188 | case '*': return STAR; 189 | case '+': return PLUS; 190 | case '?': return QUEST; 191 | case '.': return DOT; 192 | case '\0': return 0; 193 | // --- 194 | case '|': 195 | case '\n': 196 | return OR; 197 | case '(': 198 | case ')': 199 | return c; 200 | // --- 201 | case '[': 202 | x = CCL; 203 | cclcnt = 0; 204 | count = nxtchar++; 205 | if ((c = nextch()) == '^') { 206 | x = NCCL; 207 | c = nextch(); 208 | } 209 | do { 210 | if (c == '\0') 211 | syntax_error(); 212 | if ( (c == '-') 213 | && (cclcnt > 0) 214 | && (chars[nxtchar-1] != 0)) { 215 | if ((d = nextch()) != 0) { 216 | c = chars[nxtchar-1]; 217 | while ((unsigned int)c < (unsigned int)d) { 218 | if (nxtchar >= MAXLIN) 219 | table_overflow(); 220 | chars[nxtchar++] = ++c; 221 | cclcnt++; 222 | } 223 | continue; 224 | } /* if() */ 225 | } /* if() */ 226 | if (nxtchar >= MAXLIN) 227 | table_overflow(); 228 | chars[nxtchar++] = c; 229 | cclcnt++; 230 | } while ((c = nextch()) != ']'); 231 | chars[count] = cclcnt; 232 | return (x); 233 | case '\\': 234 | if ((c = nextch()) == '\0') 235 | syntax_error(); 236 | yylval = c; 237 | return (CHAR); 238 | case '$': 239 | case '^': 240 | c = '\n'; 241 | yylval = c; 242 | return (CHAR); 243 | default: 244 | yylval = c; 245 | return (CHAR); 246 | } 247 | } 248 | 249 | static 250 | void syntax_error(void) { 251 | yyerror("Syntax error"); 252 | } 253 | 254 | static 255 | unsigned int enter(int x) { 256 | if(line >= MAXLIN) 257 | table_overflow(); 258 | name[line] = x; 259 | left[line] = 0; 260 | right[line] = 0; 261 | return(line++); 262 | } 263 | 264 | static 265 | unsigned int cclenter(int x) { 266 | unsigned int linno = enter(x); 267 | right[linno] = count; 268 | return (linno); 269 | } 270 | 271 | static 272 | int node(int x, int l, int r) { 273 | if(line >= MAXLIN) 274 | table_overflow(); 275 | name[line] = x; 276 | left[line] = l; 277 | right[line] = r; 278 | parent[l] = line; 279 | parent[r] = line; 280 | return(line++); 281 | } 282 | 283 | static 284 | int unary(int x, int d) { 285 | if(line >= MAXLIN) 286 | table_overflow(); 287 | name[line] = x; 288 | left[line] = d; 289 | right[line] = 0; 290 | parent[d] = line; 291 | return(line++); 292 | } 293 | 294 | static 295 | void table_overflow(void) { 296 | yyerror("internal table overflow"); 297 | } 298 | 299 | static 300 | void cfoll(int v) { 301 | unsigned int i; 302 | 303 | if (left[v] == 0) { 304 | count = 0; 305 | for (i = 1; i <= line; i++) 306 | tmpstat[i] = 0; 307 | follow(v); 308 | add(foll, v); 309 | } else if (right[v] == 0) { 310 | cfoll(left[v]); 311 | } else { 312 | cfoll(left[v]); 313 | cfoll(right[v]); 314 | } 315 | } 316 | 317 | static 318 | void cgotofn(void) { 319 | unsigned int i, n, s; 320 | int c, k; 321 | char symbol[NCHARS]; 322 | unsigned int j, l, pc, pos; 323 | unsigned int nc; 324 | int curpos; 325 | unsigned int num, number, newpos; 326 | 327 | count = 0; 328 | for (n=3; n<=line; n++) 329 | tmpstat[n] = 0; 330 | if (cstate(line-1)==0) { 331 | tmpstat[line] = 1; 332 | count++; 333 | out[0] = 1; 334 | } 335 | for (n=3; n<=line; n++) 336 | initstat[n] = tmpstat[n]; 337 | count--; /*leave out position 1 */ 338 | icount = count; 339 | tmpstat[1] = 0; 340 | add(state, 0); 341 | n = 0; 342 | for (s = 0; s <= n; s++) { 343 | if (out[s] == 1) 344 | continue; 345 | for (i = 0; i < NCHARS; i++) 346 | symbol[i] = 0; 347 | num = positions[state[s]]; 348 | count = icount; 349 | for (i = 3; i <= line; i++) 350 | tmpstat[i] = initstat[i]; 351 | pos = state[s] + 1; 352 | for (i = 0; i < num; i++) { 353 | curpos = positions[pos]; 354 | if ((c = name[curpos]) >= 0) { 355 | if (c < NCHARS) { 356 | symbol[c] = 1; 357 | } else if (c == DOT) { 358 | for (k = 0; k < NCHARS; k++) 359 | if (k != '\n') 360 | symbol[k] = 1; 361 | } else if (c == CCL) { 362 | nc = chars[right[curpos]]; 363 | pc = right[curpos] + 1; 364 | for (j = 0; j < nc; j++) 365 | symbol[(unsigned char)chars[pc++]] = 1; 366 | } else if (c == NCCL) { 367 | nc = chars[right[curpos]]; 368 | for (j = 0; j < NCHARS; j++) { 369 | pc = right[curpos] + 1; 370 | for (l = 0; l < nc; l++) 371 | if (j==(unsigned char)chars[pc++]) 372 | goto cont; 373 | if (j != '\n') 374 | symbol[j] = 1; 375 | cont: 376 | ; 377 | } 378 | } 379 | } 380 | pos++; 381 | } /* for (i) */ 382 | for (c=0; c= 0) 392 | if ((k == c) 393 | || (k == DOT) 394 | || (k == CCL && member(c, right[curpos], 1)) 395 | || (k == NCCL && member(c, right[curpos], 0)) 396 | ) { 397 | number = positions[foll[curpos]]; 398 | newpos = foll[curpos] + 1; 399 | for (j = 0; j < number; j++) { 400 | if (tmpstat[positions[newpos]] != 1) { 401 | tmpstat[positions[newpos]] = 1; 402 | count++; 403 | } 404 | newpos++; 405 | } 406 | } 407 | pos++; 408 | } /* end nextstate */ 409 | if (notin(n)) { 410 | if (n >= NSTATES) 411 | table_overflow(); 412 | add(state, ++n); 413 | if (tmpstat[line] == 1) 414 | out[n] = 1; 415 | gotofn[s][c] = n; 416 | } else { 417 | gotofn[s][c] = xstate; 418 | } 419 | } /* if (symbol) */ 420 | } /* for(c) */ 421 | } /* for(s) */ 422 | } 423 | 424 | static int 425 | cstate(int v) 426 | { 427 | int b; 428 | if (left[v] == 0) { 429 | if (tmpstat[v] != 1) { 430 | tmpstat[v] = 1; 431 | count++; 432 | } 433 | return 1; 434 | } 435 | else if (right[v] == 0) { 436 | if (cstate(left[v]) == 0) { return 0; } 437 | else if (name[v] == PLUS) { return 1; } 438 | else { return 0; } 439 | } 440 | else if (name[v] == CAT) { 441 | if (cstate(left[v]) == 0 && cstate(right[v]) == 0) { return 0; } 442 | else { return 1; } 443 | } 444 | else { /* name[v] == OR */ 445 | b = cstate(right[v]); 446 | if (cstate(left[v]) == 0 || b == 0) { return 0; } 447 | else { return 1; } 448 | } 449 | } 450 | 451 | static 452 | int member(int symb, int set, int torf) { 453 | unsigned num = chars[set]; 454 | unsigned pos = set + 1; 455 | 456 | for (unsigned i = 0; i < num; i++) { 457 | if (symb == (unsigned char)(chars[pos++])) { 458 | return torf; 459 | } 460 | } 461 | 462 | return !torf; 463 | } 464 | 465 | static 466 | int notin(int n) { 467 | int pos; 468 | for (int i = 0; i <= n; i++) { 469 | if (positions[state[i]] == count) { 470 | pos = state[i] + 1; 471 | for (int j = 0; j < count; j++) 472 | if (tmpstat[positions[pos++]] != 1) goto nxt; 473 | xstate = i; 474 | return (0); 475 | } 476 | nxt: ; 477 | } 478 | return (1); 479 | } 480 | 481 | static 482 | void add(int *array, int n) { 483 | if (nxtpos + count > MAXPOS) 484 | table_overflow(); 485 | array[n] = nxtpos; 486 | positions[nxtpos++] = count; 487 | for (unsigned i = 3; i <= line; i++) { 488 | if (tmpstat[i] == 1) { 489 | positions[nxtpos++] = i; 490 | } 491 | } 492 | } 493 | 494 | static 495 | void follow(unsigned int v) { 496 | if (v == line) { return; } 497 | 498 | unsigned int p = parent[v]; 499 | switch(name[p]) { 500 | case STAR: 501 | case PLUS: 502 | cstate(v); 503 | follow(p); 504 | break; 505 | case OR: 506 | case QUEST: 507 | follow(p); 508 | break; 509 | case CAT: 510 | if (v == left[p] 511 | && cstate(right[p]) != 0) { 512 | return; 513 | } 514 | follow(p); 515 | return; 516 | case FINAL: 517 | if (tmpstat[line] != 1) { 518 | tmpstat[line] = 1; 519 | count++; 520 | } 521 | break; 522 | } 523 | } 524 | 525 | char * egrepinit(const char *egreppat) { 526 | /* initialize the global data */ 527 | memset(gotofn, 0, sizeof(gotofn)); 528 | memset(state, 0, sizeof(state)); 529 | memset(out, 0, sizeof(out)); 530 | line = 1; 531 | memset(name, 0, sizeof(name)); 532 | memset(left, 0, sizeof(left)); 533 | memset(right, 0, sizeof(right)); 534 | memset(parent, 0, sizeof(parent)); 535 | memset(foll, 0, sizeof(foll)); 536 | memset(positions, 0, sizeof(positions)); 537 | memset(chars, 0, sizeof(chars)); 538 | nxtpos = 0; 539 | nxtchar = 0; 540 | memset(tmpstat, 0, sizeof(tmpstat)); 541 | memset(initstat, 0, sizeof(initstat)); 542 | xstate = 0; 543 | count = 0; 544 | icount = 0; 545 | input = egreppat; 546 | message = NULL; 547 | if (setjmp(env) == 0) { 548 | yyparse(); 549 | cfoll(line-1); 550 | cgotofn(); 551 | } 552 | return(message); 553 | } 554 | 555 | static char buf[2 * BUFSIZ]; 556 | static const char *buf_end = buf + (sizeof(buf) / sizeof(*buf)); 557 | 558 | static 559 | size_t read_next_chunk(char **p, FILE *fptr) 560 | { 561 | if (*p <= (buf + BUFSIZ)) { 562 | /* bwlow the middle, so enough space left for one entire BUFSIZ */ 563 | return fread(*p, sizeof(**p), BUFSIZ, fptr); 564 | } else if (*p == buf_end) { 565 | /* exactly at end ... wrap around and use lower half */ 566 | *p = buf; 567 | return fread(*p, sizeof(**p), BUFSIZ, fptr); 568 | } 569 | /* somewhere in second half, so do a limited read */ 570 | return fread(*p, sizeof(**p), buf_end - *p, fptr); 571 | } 572 | 573 | int egrep(const char * file, FILE *output, char *format) { 574 | char *p; 575 | unsigned int cstat; 576 | int ccount; 577 | char *nlp; 578 | unsigned int istat; 579 | int in_line; 580 | FILE *fptr; 581 | 582 | if ((fptr = myfopen(file, "r")) == NULL) 583 | return(-1); 584 | 585 | lnum = 1; 586 | p = buf; 587 | nlp = p; 588 | ccount = read_next_chunk(&p, fptr); 589 | 590 | if (ccount <= 0) { 591 | fclose(fptr); 592 | return(0); 593 | } 594 | in_line = 1; 595 | istat = cstat = (unsigned int) gotofn[0]['\n']; 596 | if (out[cstat]) 597 | goto found; 598 | for (;;) { 599 | if (!iflag) { 600 | /* all input chars made positive */ 601 | cstat = (unsigned int) gotofn[cstat][(unsigned char)*p]; 602 | } else { 603 | /* for -i option*/ 604 | cstat = (unsigned int) gotofn[cstat][tolower((unsigned char)*p)]; 605 | } 606 | if (out[cstat]) { 607 | found: 608 | for(;;) { 609 | if (*p++ == '\n') { 610 | in_line = 0; 611 | succeed: 612 | fprintf(output, format, file, lnum); 613 | if (p <= nlp) { 614 | while (nlp < buf_end) 615 | putc(*nlp++, output); 616 | nlp = buf; 617 | } 618 | while (nlp < p) 619 | putc(*nlp++, output); 620 | lnum++; 621 | nlp = p; 622 | if (out[cstat = istat] == 0) 623 | goto brk2; 624 | } /* if (p++ == \n) */ 625 | cfound: 626 | if (--ccount <= 0) { 627 | ccount = read_next_chunk(&p, fptr); 628 | if (ccount <= 0) { 629 | if (in_line) { 630 | in_line = 0; 631 | goto succeed; 632 | } 633 | fclose(fptr); 634 | return(0); 635 | } 636 | } /* if(ccount <= 0) */ 637 | in_line = 1; 638 | } /* for(ever) */ 639 | } /* if(out[cstat]) */ 640 | 641 | if (*p++ == '\n') { 642 | in_line = 0; 643 | lnum++; 644 | nlp = p; 645 | if (out[(cstat=istat)]) 646 | goto cfound; 647 | } 648 | brk2: 649 | if (--ccount <= 0) { 650 | ccount = read_next_chunk(&p, fptr); 651 | if (ccount <= 0) 652 | break; 653 | } 654 | in_line = 1; 655 | } 656 | fclose(fptr); 657 | return(0); 658 | } 659 | 660 | void egrepcaseless(int i) { 661 | iflag = i; /* simulate "egrep -i" */ 662 | } 663 | -------------------------------------------------------------------------------- /source/exec.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * process execution functions 36 | */ 37 | 38 | #include 39 | #include "global.h" 40 | #include 41 | #include 42 | #include /* pid_t */ 43 | #ifdef __DJGPP__ 44 | # include 45 | #endif 46 | #include 47 | 48 | static sighandler_t oldsigquit; /* old value of quit signal */ 49 | static sighandler_t oldsighup; /* old value of hangup signal */ 50 | static sighandler_t oldsigtstp; /* old value of SIGTSTP */ 51 | 52 | #ifndef __MSDOS__ /* none of these is needed, there */ 53 | static int join(pid_t p); 54 | static int myexecvp(char *a, char **args); 55 | static pid_t myfork(void); 56 | #endif 57 | 58 | /* execute forks and executes a program or shell script, waits for it to 59 | * finish, and returns its exit code. 60 | */ 61 | int execute(char *a, ...) /* NOTE: "exec" is already defined on u370 */ 62 | { 63 | va_list ap; 64 | int exitcode = -1; 65 | char *argv[BUFSIZ]; 66 | pid_t p; 67 | 68 | /* fork and exec the program or shell script */ 69 | endwin(); /* restore the terminal modes */ 70 | mousecleanup(); 71 | fflush(stdout); 72 | va_start(ap, a); 73 | 74 | for(p = 0; (argv[p] = va_arg(ap, char *)) != 0; p++) { ; } 75 | 76 | #ifdef __MSDOS__ 77 | /* HBB 20010313: in MSDOG, everything is completely different. 78 | * No fork()/exec()/wait(), but rather a single libc call: */ 79 | exitcode = spawnvp(P_WAIT, a, argv); 80 | #else 81 | if((p = myfork()) == 0) { 82 | myexecvp(a, argv); /* child */ 83 | } else { 84 | exitcode = join(p); /* parent */ 85 | } 86 | #endif /* MSDOS */ 87 | 88 | entercurses(); 89 | 90 | va_end(ap); 91 | return (exitcode); 92 | } 93 | 94 | #ifndef __MSDOS__ /* None of the following functions is used there */ 95 | 96 | /* myexecvp is an interface to the execvp system call to 97 | * modify argv[0] to reference the last component of its path-name. 98 | */ 99 | static int myexecvp(char *a, char **args) { 100 | char msg[MSGLEN + 1]; 101 | 102 | /* modify argv[0] to reference the last component of its path name */ 103 | args[0] = (char *)basename(args[0]); 104 | 105 | /* execute the program or shell script */ 106 | execvp(a, args); /* returns only on failure */ 107 | snprintf(msg, sizeof(msg), "\nCannot exec %s", a); 108 | perror(msg); /* display the reason */ 109 | askforreturn(); /* wait until the user sees the message */ 110 | myexit(1); /* exit the child */ 111 | /* NOTREACHED */ 112 | return 0; 113 | } 114 | 115 | /* myfork acts like fork but also handles signals */ 116 | 117 | static pid_t myfork(void) { 118 | pid_t p; /* process number */ 119 | 120 | p = fork(); 121 | 122 | /* the parent ignores the interrupt, quit, and hangup signals */ 123 | if(p > 0) { 124 | oldsigquit = signal(SIGQUIT, SIG_IGN); 125 | oldsighup = signal(SIGHUP, SIG_IGN); 126 | # ifdef SIGTSTP 127 | oldsigtstp = signal(SIGTSTP, SIG_DFL); 128 | # endif 129 | } 130 | /* so they can be used to stop the child */ 131 | else if(p == 0) { 132 | signal(SIGINT, SIG_DFL); 133 | signal(SIGQUIT, SIG_DFL); 134 | signal(SIGHUP, SIG_DFL); 135 | # ifdef SIGTSTP 136 | signal(SIGTSTP, SIG_DFL); 137 | # endif 138 | } 139 | /* check for fork failure */ 140 | if(p == -1) { myperror("Cannot fork"); } 141 | return p; 142 | } 143 | 144 | /* join is the compliment of fork */ 145 | static int join(pid_t p) { 146 | int status = -1; 147 | pid_t w; 148 | 149 | /* wait for the correct child to exit */ 150 | do { 151 | w = wait(&status); 152 | } while(p != -1 && w != p); 153 | 154 | /* restore signal handling */ 155 | signal(SIGQUIT, oldsigquit); 156 | signal(SIGHUP, oldsighup); 157 | # ifdef SIGTSTP 158 | signal(SIGTSTP, oldsigtstp); 159 | # endif 160 | 161 | /* return the child's exit code */ 162 | return (status >> 8); 163 | } 164 | 165 | #endif /* !MSDOS */ 166 | -------------------------------------------------------------------------------- /source/global.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * global type, data, and function definitions 36 | */ 37 | 38 | #ifndef CSCOPE_GLOBAL_H 39 | #define CSCOPE_GLOBAL_H 40 | 41 | #define UNUSED(x) (void)(x) 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include /* isalpha, isdigit, etc. */ 48 | #include 49 | #include 50 | #include 51 | 52 | #include /* string functions */ 53 | 54 | #include "constants.h" /* misc. constants */ 55 | #include "invlib.h" /* inverted index library */ 56 | #include "library.h" /* library function return values */ 57 | 58 | typedef void (*sighandler_t)(int); 59 | 60 | struct cmd { /* command history struct */ 61 | struct cmd *prev, *next; /* list ptrs */ 62 | int field; /* input field number */ 63 | char *text; /* input field text */ 64 | }; 65 | 66 | /* bitmask type to mark which windows have to be rerendered by display() 67 | */ 68 | enum { 69 | CH_NONE = 0x0000, 70 | CH_RESULT = 0x0001 << 0, 71 | CH_INPUT = 0x0001 << 1, 72 | CH_MODE = 0x0001 << 2, 73 | CH_CASE = 0x0001 << 3, 74 | CH_HELP = 0x0001 << 4, /* do NOT add to CH_ALL */ 75 | CH_ALL = CH_RESULT | CH_INPUT | CH_MODE | CH_CASE 76 | }; 77 | /* Only display.c can directly update the screen. 78 | * Any other component must request the update of a particular 79 | * screen area by OR'ing this variable with the appropriate mask. 80 | */ 81 | extern int window_change; 82 | 83 | enum { 84 | INPUT_NORMAL, 85 | INPUT_APPEND, 86 | INPUT_PIPE, 87 | INPUT_READ, 88 | INPUT_CHANGE_TO, 89 | INPUT_CHANGE 90 | }; 91 | extern int input_mode; 92 | 93 | #define DEFAULT_INCLUDE_DIRECTORY "/usr/include" 94 | extern const char * incdir; 95 | 96 | /* digraph data for text compression */ 97 | extern char dichar1[]; /* 16 most frequent first chars */ 98 | extern char dichar2[]; /* 8 most frequent second chars using the above as first chars */ 99 | extern char dicode1[]; /* digraph first character code */ 100 | extern char dicode2[]; /* digraph second character code */ 101 | 102 | /* and some macros to help using dicodes: */ 103 | /* Check if a given pair of chars is compressable as a dicode: */ 104 | #define IS_A_DICODE(inchar1, inchar2) \ 105 | (dicode1[(unsigned char)(inchar1)] && dicode2[(unsigned char)(inchar2)]) 106 | /* Combine the pair into a dicode */ 107 | #define DICODE_COMPRESS(inchar1, inchar2) \ 108 | ((0200 - 2) + dicode1[(unsigned char)(inchar1)] + dicode2[(unsigned char)(inchar2)]) 109 | 110 | #define PROGRAM_NAME "Csope" 111 | 112 | /* main.c global data */ 113 | extern char *editor, /* EDITOR env var */ 114 | *home, /* Home directory */ 115 | *shell, /* Users shell */ 116 | *lineflag; /* Flag used to open EDITOR at a specified line */ 117 | 118 | extern bool lineflagafterfile; 119 | extern bool compress; /* compress the characters in the crossref */ 120 | extern bool dbtruncated; /* database symbols truncated to 8 chars */ 121 | extern int dispcomponents; /* file path components to display */ 122 | extern bool editallprompt; /* prompt between editing files */ 123 | extern int fileversion; /* cross-reference file version */ 124 | extern bool incurses; /* in curses */ 125 | extern bool invertedindex; /* the database has an inverted index */ 126 | extern bool preserve_database; /* consider the crossref up-to-date */ 127 | extern bool kernelmode; /* don't use DEFAULT_INCLUDE_DIRECTORY - bad for kernels */ 128 | extern bool linemode; /* use line oriented user interface */ 129 | extern bool verbosemode; /* print extra information on line mode */ 130 | extern bool recurse_dir; /* recurse dirs when searching for src files */ 131 | extern char *namefile; /* file of file names */ 132 | extern char *prependpath; /* prepend path to file names */ 133 | extern FILE *refsfound; /* references found file */ 134 | extern long totalterms; /* total inverted index terms */ 135 | extern bool trun_syms; /* truncate symbols to 8 characters */ 136 | extern char tempstring[TEMPSTRING_LEN + 1]; /* global dummy string buffer */ 137 | 138 | extern const char * const * fileargv; /* file argument values */ 139 | 140 | extern char *tmpdir; /* temporary directory */ 141 | extern char temp1[]; /* temporary file name */ 142 | extern char temp2[]; /* temporary file name */ 143 | 144 | /* command.c global data */ 145 | extern bool caseless; /* ignore letter case when searching */ 146 | extern bool *change; /* change this line */ 147 | extern unsigned int curdispline; 148 | extern char newpat[]; /* new pattern */ 149 | 150 | /* crossref.c global data */ 151 | extern long dboffset; /* new database offset */ 152 | extern bool errorsfound; /* prompt before clearing error messages */ 153 | extern long lineoffset; /* source line database offset */ 154 | extern long npostings; /* number of postings */ 155 | extern unsigned long symbols; /* number of symbols */ 156 | 157 | /* dir.c global data */ 158 | extern char currentdir[]; /* current directory */ 159 | extern char **incdirs; /* #include directories */ 160 | extern char **srcdirs; /* source directories */ 161 | extern char **srcfiles; /* source files */ 162 | extern size_t nincdirs; /* number of #include directories */ 163 | extern size_t nsrcdirs; /* number of source directories */ 164 | extern size_t nsrcfiles; /* number of source files */ 165 | extern size_t msrcfiles; /* maximum number of source files */ 166 | 167 | /* display.c global data */ 168 | extern int filelen; /* file name display field length */ 169 | extern int fcnlen; /* function name display field length */ 170 | extern int numlen; /* line number display field length */ 171 | extern unsigned int disprefs; /* displayed references */ 172 | extern int field; /* input field */ 173 | extern unsigned int mdisprefs; /* maximum displayed references */ 174 | extern unsigned int nextline; /* next line to be shown */ 175 | extern long searchcount; /* count of files searched */ 176 | extern unsigned int totallines; /* total reference lines */ 177 | 178 | /* find.c global data */ 179 | extern char block[]; /* cross-reference file block */ 180 | extern char blockmark; /* mark character to be searched for */ 181 | extern long blocknumber; /* block number */ 182 | extern char *blockp; /* pointer to current character in block */ 183 | extern int blocklen; /* length of disk block read */ 184 | 185 | /* lookup.c global data */ 186 | extern struct keystruct { 187 | const char * text; 188 | const char delim; 189 | struct keystruct *next; 190 | } keyword[]; 191 | 192 | /* readline.c global data */ 193 | extern char *rl_line_buffer; 194 | extern char input_line[PATLEN + 1]; 195 | extern int rl_point; 196 | 197 | /* cscope functions called from more than one function or between files */ 198 | 199 | const char * prepend_path(const char * prepand_with, const char * file); 200 | char *inviewpath(const char *file); 201 | char *lookup(char *ident, bool do_compressed); 202 | char *pathcomponents(char *path, int components); 203 | char *read_crossreference_block(void); 204 | char *scanpast(char c); 205 | 206 | char **parse_options(const int argc, const char * const * const argv); 207 | void readenv(bool preserve_database); 208 | 209 | extern bool remove_symfile_onexit; 210 | extern bool onesearch; /* one search only in line mode */ 211 | extern char *reflines; /* symbol reference lines file */ 212 | extern bool do_press_any_key; /* wait for any key to continue */ 213 | extern int current_page; 214 | #define topref (current_page * mdisprefs) 215 | void horswp_window(void); 216 | void verswp_window(void); 217 | bool interpret(int c); // XXX: probably rename 218 | int handle_input(const int c); 219 | int dispchar2int(const char c); 220 | int changestring(const char *from, const char *to, const bool *const change, const int change_len); 221 | 222 | void init_temp_files(void); 223 | void deinit_temp_files(void); 224 | 225 | long seekpage(const size_t i); 226 | long seekrelline(unsigned i); 227 | void PCS_reset(void); 228 | 229 | void rlinit(void); 230 | 231 | void addsrcfile(char *path); 232 | void askforchar(void); 233 | void askforreturn(void); 234 | void cannotwrite(const char *const file); 235 | void cannotopen(const char *const file); 236 | void clearmsg(void); 237 | void clearmsg2(void); 238 | void countrefs(void); 239 | void crossref(char *srcfile); 240 | void edit(const char * filename, const char *const linenum); 241 | void editall(void); 242 | void editref(int); 243 | void force_window(void); 244 | void findcleanup(void); 245 | void freesrclist(void); 246 | void freeinclist(void); 247 | void freecrossref(void); 248 | void freefilelist(void); 249 | void incfile(char *file, char *type); 250 | void includedir(const char *dirname); 251 | void initsymtab(void); 252 | void makefilelist(const char * const * const argv); 253 | void myexit(int sig); 254 | void myperror(char *text); 255 | void progress(char *what, long current, long max); 256 | void putfilename(char *srcfile); 257 | void postmsg(char *msg); 258 | void postmsg2(char *msg); 259 | void posterr(char *msg, ...); 260 | void postfatal(const char *msg, ...); 261 | void putposting(char *term, int type); 262 | void fetch_string_from_dbase(char *, size_t); 263 | void sourcedir(const char * dirlist); 264 | void myungetch(int c); 265 | void warning(char *text); 266 | void writestring(char *s); 267 | 268 | void entercurses(void); 269 | void exitcurses(void); 270 | void drawscrollbar(int top, int bot); 271 | void dispinit(void); 272 | void display(void); 273 | void redisplay(void); 274 | 275 | void shellpath(char *out, int limit, char *in); 276 | 277 | bool infilelist(const char * file); 278 | bool readrefs(char *filename); 279 | bool search(const char *query); 280 | bool writerefsfound(void); 281 | 282 | int findinit(const char *pattern_); 283 | 284 | int egrep(const char * file, FILE *output, char *format); 285 | int hash(const char * ss); 286 | int execute(char *a, ...); 287 | long dbseek(long offset); 288 | 289 | void mousecleanup(void); 290 | int process_mouse(void); 291 | 292 | #endif /* CSCOPE_GLOBAL_H */ 293 | -------------------------------------------------------------------------------- /source/gscope.c: -------------------------------------------------------------------------------- 1 | /* Placeholder file --- replace by real gscope.c if you have it */ 2 | -------------------------------------------------------------------------------- /source/help.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * display help 36 | * 37 | */ 38 | 39 | #include "global.h" 40 | #include 41 | /* 42 | max num of lines of help screen - 43 | this number needs to be increased if more than n help items are needed 44 | */ 45 | 46 | const char tooltip_winput[] = "Search [Enter] -Mode [^k] +Mode [^j] Right [Tab] Down [%]"; 47 | const char tooltip_wmode[] = "-Mode [Up] +Mode [Down] Right [Tab] Up [%]"; 48 | const char tooltip_wresult[] = 49 | "Edit [Enter] Up [Up] Down [Down] Left [Tab] Previous [-] Next [+]"; 50 | 51 | static char help_msg[] = 52 | "Press the RETURN key repeatedly to move to the desired input field, type the\n" 53 | "pattern to search for, and then press the RETURN key. For the first 4 and\n" 54 | "last 2 input fields, the pattern can be a regcomp(3) regular expression.\n" 55 | "If the search is successful, you can use these single-character commands:\n\n" 56 | "0-9a-zA-Z\tEdit the file containing the displayed line.\n" 57 | "space bar\tDisplay next set of matching lines.\n" 58 | "+\t\tDisplay next set of matching lines.\n" 59 | "^V\t\tDisplay next set of matching lines.\n" 60 | "-\t\tDisplay previous set of matching lines.\n" 61 | "^E\t\tEdit all lines.\n" 62 | ">\t\tWrite the list of lines being displayed to a file.\n" 63 | ">>\t\tAppend the list of lines being displayed to a file.\n" 64 | "<\t\tRead lines from a file.\n" 65 | "^\t\tFilter all lines through a shell command.\n" 66 | "|\t\tPipe all lines to a shell command.\n" 67 | "\nAt any time you can use these single-character commands:\n\n" 68 | "TAB\t\tSwap positions between input and output areas.\n" 69 | "RETURN\t\tMove to the next input field.\n" 70 | "^N\t\tMove to the next input field.\n" 71 | "^P\t\tMove to the previous input field.\n" 72 | "^Y / ^A\t\tSearch with the last pattern typed.\n" 73 | "^B\t\tRecall previous input field and search pattern.\n" 74 | "^F\t\tRecall next input field and search pattern.\n" 75 | "^C\t\tToggle ignore/use letter case when searching.\n" 76 | "^R\t\tRebuild the cross-reference.\n" 77 | "!\t\tStart an interactive shell (type ^D to return).\n" 78 | "^L\t\tRedraw the screen.\n" 79 | "?\t\tDisplay this list of commands.\n" 80 | "^D\t\tExit the program.\n" 81 | "\nNote: If the first character of the pattern you want to search for matches\n" 82 | "a command, type a \\ character first.\n" 83 | "Note: Some ctrl keys may be occupied by your terminal configuration.\n" 84 | ; 85 | 86 | static char changeing_help_msg[] = 87 | "When changing text, you can use these single-character commands:\n\n" 88 | "0-9a-zA-Z\tMark or unmark the line to be changed.\n" 89 | "*\t\tMark or unmark all displayed lines to be changed.\n" 90 | "space bar\tDisplay next set of lines.\n" 91 | "+\t\tDisplay next set of lines.\n" 92 | "-\t\tDisplay previous set of lines.\n" 93 | "^A\t\tMark or unmark all lines to be changed.\n" 94 | "^D\t\tChange the marked lines and exit.\n" 95 | "ESC\t\tExit without changing the marked lines.\n" 96 | "!\t\tStart an interactive shell (type ^D to return).\n" 97 | "^L\t\tRedraw the screen.\n" 98 | "?\t\tDisplay this list of commands.\n" 99 | ; 100 | 101 | const char * help(void) { 102 | switch (input_mode) { 103 | case INPUT_CHANGE: 104 | case INPUT_CHANGE_TO: 105 | return changeing_help_msg; 106 | default: 107 | return help_msg; 108 | } 109 | } 110 | 111 | /* normal usage message */ 112 | void usage(void) { 113 | fputs("Usage: " PROGRAM_NAME 114 | " [-bcCdehklLqRTuUvV] [-f file] [-F file] [-i file] [-I dir] [-s dir]\n" 115 | " [-p number] [-P path] [-[0-8] pattern] [source files]\n", 116 | stderr); 117 | } 118 | 119 | /* long usage message */ 120 | void longusage(void) { 121 | usage(); 122 | fprintf(stderr, 123 | "\ 124 | \n\ 125 | -b Build the cross-reference only.\n\ 126 | -C Ignore letter case when searching.\n\ 127 | -c Use only ASCII characters in the cross-ref file (don't compress).\n\ 128 | -d Do not update the cross-reference.\n\ 129 | -e Suppress the -e command prompt between files.\n\ 130 | -F symfile Read symbol reference lines from symfile.\n\ 131 | -f reffile Use reffile as cross-ref file name instead of %s.\n", 132 | REFFILE); 133 | fprintf(stderr, 134 | "\ 135 | -h This help screen.\n\ 136 | -I incdir Look in incdir for any #include files.\n\ 137 | -i namefile Browse through files listed in namefile, instead of %s\n", 138 | NAMEFILE); 139 | fprintf(stderr, 140 | "\ 141 | -k Kernel Mode - don't use %s for #include files.\n", 142 | DEFAULT_INCLUDE_DIRECTORY); 143 | fputs("\ 144 | -L Do a single search with line-oriented output.\n\ 145 | -l Line-oriented interface.\n\ 146 | -num pattern Go to input field num (counting from 0) and find pattern.\n\ 147 | -P path Prepend path to relative file names in pre-built cross-ref file.\n\ 148 | -p n Display the last n file path components.\n\ 149 | -q Build an inverted index for quick symbol searching.\n\ 150 | -R Recurse directories for files.\n\ 151 | -s dir Look in dir for additional source files.\n\ 152 | -T Use only the first eight characters to match against C symbols.\n\ 153 | -U Check file time stamps.\n\ 154 | -u Unconditionally build the cross-reference file.\n\ 155 | -v Be more verbose in line mode.\n\ 156 | -V Print the version number.\n\ 157 | \n\ 158 | Please see the manpage for more information.\n", 159 | stderr); 160 | } 161 | -------------------------------------------------------------------------------- /source/help.h: -------------------------------------------------------------------------------- 1 | #ifndef HELP_H 2 | #define HELP_H 3 | 4 | const char *help(void); 5 | void longusage(void); 6 | void usage(void); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /source/input.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * terminal input functions 36 | */ 37 | 38 | #include "global.h" 39 | #include "build.h" 40 | #include 41 | #include /* jmp_buf */ 42 | #include 43 | #include 44 | #include 45 | #if HAVE_SYS_TERMIOS_H 46 | # include 47 | #endif 48 | 49 | #include "keys.h" 50 | 51 | extern const void *const winput; 52 | extern const void *const wmode; 53 | extern const void *const wresult; 54 | extern const void *const *const current_window; 55 | 56 | bool do_press_any_key = false; 57 | 58 | static jmp_buf env; /* setjmp/longjmp buffer */ 59 | static int prevchar; /* previous, ungotten character */ 60 | 61 | /* Internal prototypes: */ 62 | static void catchint(int sig); 63 | 64 | /* catch the interrupt signal */ 65 | 66 | static void catchint(int sig) { 67 | UNUSED(sig); 68 | 69 | signal(SIGINT, catchint); 70 | longjmp(env, 1); 71 | } 72 | 73 | static inline 74 | bool rebuild_reference() { 75 | if(preserve_database == true) { 76 | postmsg("The -d option prevents rebuilding the symbol database"); 77 | return false; 78 | } 79 | exitcurses(); 80 | freefilelist(); /* remake the source file list */ 81 | makefilelist(fileargv); 82 | rebuild(); 83 | if(errorsfound == true) { 84 | errorsfound = false; 85 | askforreturn(); 86 | } 87 | entercurses(); 88 | postmsg(""); /* clear any previous message */ 89 | totallines = 0; 90 | disprefs = 0; 91 | return true; 92 | } 93 | 94 | /* unget a character */ 95 | void myungetch(int c) { 96 | prevchar = c; 97 | } 98 | 99 | /* ask user to enter a character after reading the message */ 100 | void askforchar(void) { 101 | addstr("Type any character to continue: "); 102 | getch(); 103 | } 104 | 105 | /* ask user to press the RETURN key after reading the message */ 106 | void askforreturn(void) { 107 | fprintf(stderr, "Press the RETURN key to continue: "); 108 | getchar(); 109 | /* HBB 20060419: message probably messed up the screen --- redraw */ 110 | if(incurses == true) { redrawwin(curscr); } 111 | } 112 | 113 | /* expand the ~ and $ shell meta characters in a path */ 114 | void shellpath(char *out, int limit, char *in) { 115 | char *lastchar; 116 | char *s, *v; 117 | 118 | /* skip leading white space */ 119 | while(isspace((unsigned char)*in)) { 120 | ++in; 121 | } 122 | lastchar = out + limit - 1; 123 | 124 | /* a tilde (~) by itself represents $HOME; followed by a name it 125 | represents the $LOGDIR of that login name */ 126 | if(*in == '~') { 127 | *out++ = *in++; /* copy the ~ because it may not be expanded */ 128 | 129 | /* get the login name */ 130 | s = out; 131 | while(s < lastchar && *in != '/' && *in != '\0' && !isspace((unsigned char)*in)) { 132 | *s++ = *in++; 133 | } 134 | *s = '\0'; 135 | 136 | /* if the login name is null, then use $HOME */ 137 | if(*out == '\0') { 138 | v = getenv("HOME"); 139 | } else { /* get the home directory of the login name */ 140 | v = logdir(out); 141 | } 142 | /* copy the directory name if it isn't too big */ 143 | if(v != NULL && strlen(v) < (lastchar - out)) { 144 | strcpy(out - 1, v); 145 | out += strlen(v) - 1; 146 | } else { 147 | /* login not found, so ~ must be part of the file name */ 148 | out += strlen(out); 149 | } 150 | } 151 | /* get the rest of the path */ 152 | while(out < lastchar && *in != '\0' && !isspace((unsigned char)*in)) { 153 | 154 | /* look for an environment variable */ 155 | if(*in == '$') { 156 | *out++ = *in++; /* copy the $ because it may not be expanded */ 157 | 158 | /* get the variable name */ 159 | s = out; 160 | while(s < lastchar && *in != '/' && *in != '\0' && 161 | !isspace((unsigned char)*in)) { 162 | *s++ = *in++; 163 | } 164 | *s = '\0'; 165 | 166 | /* get its value, but only it isn't too big */ 167 | if((v = getenv(out)) != NULL && strlen(v) < (lastchar - out)) { 168 | strcpy(out - 1, v); 169 | out += strlen(v) - 1; 170 | } else { 171 | /* var not found, or too big, so assume $ must be part of the 172 | * file name */ 173 | out += strlen(out); 174 | } 175 | } else { /* ordinary character */ 176 | *out++ = *in++; 177 | } 178 | } 179 | *out = '\0'; 180 | } 181 | 182 | static int wmode_input(const int c) { 183 | switch(c) { 184 | case KEY_ENTER: 185 | case '\r': 186 | case '\n': 187 | case ctrl('N'): /* go to next input field */ 188 | case KEY_DOWN: 189 | case KEY_RIGHT: 190 | field = (field + 1) % FIELDS; 191 | break; 192 | case ctrl('P'): /* go to previous input field */ 193 | case KEY_UP: 194 | case KEY_LEFT: 195 | field = (field + (FIELDS - 1)) % FIELDS; 196 | break; 197 | case KEY_HOME: /* go to first input field */ 198 | field = 0; 199 | break; 200 | case KEY_LL: /* go to last input field */ 201 | curdispline = disprefs; 202 | break; 203 | default: 204 | return 0; 205 | } 206 | 207 | window_change |= CH_MODE; 208 | return 1; 209 | } 210 | 211 | static int wresult_input(const int c) { 212 | switch(c) { 213 | case KEY_ENTER: /* open for editing */ 214 | case '\r': 215 | case '\n': 216 | editref(curdispline); 217 | window_change = CH_ALL; 218 | break; 219 | case ctrl('N'): 220 | case KEY_DOWN: 221 | case KEY_RIGHT: 222 | if((curdispline + 1) < disprefs) { ++curdispline; } 223 | break; 224 | case ctrl('P'): 225 | case KEY_UP: 226 | case KEY_LEFT: 227 | if(curdispline) { --curdispline; } 228 | break; 229 | case KEY_HOME: 230 | curdispline = 0; 231 | break; 232 | case KEY_LL: 233 | field = FIELDS - 1; 234 | break; 235 | default: 236 | if(c > mdisprefs) { goto noredisp; } 237 | const int pos = dispchar2int(c); 238 | if(pos > -1) { editref(pos); } 239 | goto noredisp; 240 | } 241 | 242 | window_change |= CH_RESULT; 243 | noredisp: 244 | return 1; 245 | } 246 | 247 | static 248 | int global_input(const int c) { 249 | switch(c) { 250 | case '\t': 251 | horswp_window(); 252 | break; 253 | case '%': 254 | verswp_window(); 255 | break; 256 | case ctrl('R'): 257 | rebuild_reference(); 258 | break; 259 | case ctrl('K'): 260 | field = (field + (FIELDS - 1)) % FIELDS; 261 | window_change |= CH_MODE; 262 | break; 263 | case ctrl('J'): 264 | field = (field + 1) % FIELDS; 265 | window_change |= CH_MODE; 266 | break; 267 | case ctrl('H'): /* display previous page */ 268 | case '-': 269 | case KEY_PPAGE: 270 | if(totallines == 0) { return 0; } /* don't redisplay if there are no lines */ 271 | curdispline = 0; 272 | if(current_page > 0) { 273 | --current_page; 274 | window_change |= CH_RESULT; 275 | } 276 | break; 277 | case '+': 278 | case KEY_NPAGE: 279 | if(totallines == 0) { return 0; } /* don't redisplay if there are no lines */ 280 | curdispline = 0; 281 | ++current_page; 282 | window_change |= CH_RESULT; 283 | break; 284 | case '!': /* shell escape */ 285 | execute(shell, shell, NULL); 286 | current_page = 0; 287 | break; 288 | case ctrl('U'): /* redraw screen */ 289 | case KEY_CLEAR: 290 | window_change = CH_ALL; 291 | break; 292 | case '?': /* help */ 293 | window_change = CH_HELP; 294 | break; 295 | case ctrl('E'): /* edit all lines */ 296 | editall(); 297 | break; 298 | case ctrl('S'): // toggle caseless 299 | caseless = !caseless; 300 | egrepcaseless(caseless); 301 | window_change |= CH_CASE; 302 | break; 303 | case EOF: 304 | myexit(0); 305 | break; 306 | default: 307 | return 0; 308 | } 309 | 310 | return 1; 311 | } 312 | 313 | int normal_global_input(const int c) { 314 | switch(c) { 315 | case '>': /* write or append the lines to a file */ 316 | if (totallines == 0) { 317 | postmsg("There are no lines to write to a file"); 318 | break; 319 | } 320 | input_mode = INPUT_APPEND; 321 | window_change |= CH_INPUT; 322 | force_window(); 323 | break; 324 | case '<': /* read lines from a file */ 325 | input_mode = INPUT_READ; 326 | window_change |= CH_INPUT; 327 | force_window(); 328 | break; 329 | case '|': /* pipe the lines to a shell command */ 330 | case '^': 331 | break; // XXX fix 332 | if(totallines == 0) { 333 | postmsg("There are no lines to pipe to a shell command"); 334 | break; 335 | } 336 | /* get the shell command */ 337 | // move(PRLINE, 0); 338 | // addstr(pipeprompt); 339 | // if (mygetline("", newpat, COLS - sizeof(pipeprompt), '\0', NO) == 0) { 340 | // clearprompt(); 341 | // return(NO); 342 | // } 343 | ///* if the ^ command, redirect output to a temp file */ 344 | // if (commandc == '^') { 345 | // strcat(strcat(newpat, " >"), temp2); 346 | // /* HBB 20020708: somebody might have even 347 | // * their non-interactive default shells 348 | // * complain about clobbering 349 | // * redirections... --> delete before 350 | // * overwriting */ 351 | // remove(temp2); 352 | // } 353 | // exitcurses(); 354 | // if ((file = mypopen(newpat, "w")) == NULL) { 355 | // fprintf(stderr, "cscope: cannot open pipe to shell command: %s\n", 356 | // newpat); 357 | // } else { 358 | // seekline(1); 359 | // while ((c = getc(refsfound)) != EOF) { 360 | // putc(c, file); 361 | // } 362 | // seekline(topline); 363 | // mypclose(file); 364 | // } 365 | // if (commandc == '^') { 366 | // if (readrefs(temp2) == NO) { 367 | // postmsg("Ignoring empty output of ^ command"); 368 | // } 369 | // } 370 | // askforreturn(); 371 | // entercurses(); 372 | break; 373 | default: 374 | return 0; 375 | } 376 | 377 | return 1; 378 | } 379 | 380 | int change_input(const int c) { 381 | switch(c) { 382 | case '*': /* invert page */ 383 | for(unsigned i = 0; i < (nextline-1); i++) { 384 | change[topref + i] = !change[topref + i]; 385 | } 386 | window_change |= CH_RESULT; 387 | break; 388 | case ctrl('A'): /* invert all lines */ 389 | for(unsigned i = 0; i < totallines; i++) { 390 | change[i] = !change[i]; 391 | } 392 | window_change |= CH_RESULT; 393 | break; 394 | /* MOUSE SELECTION 395 | case ctrl('X'): 396 | MOUSE *p; 397 | if((p = getmouseaction(DUMMYCHAR)) == NULL) { 398 | break; // unknown control sequence 399 | } 400 | // if the button number is a scrollbar tag 401 | if(p->button == '0') { 402 | // scrollbar(p); 403 | break; 404 | } 405 | // find the selected line 406 | // NOTE: the selection is forced into range 407 | { 408 | int i; 409 | for(i = disprefs - 1; i > 0; --i) { 410 | if(p->y1 >= displine[i]) { break; } 411 | } 412 | change[i] = !change[i]; 413 | } 414 | break; 415 | */ 416 | case ctrl('D'): 417 | changestring(input_line, newpat, change, totallines); 418 | free(change); 419 | change = NULL; 420 | input_mode = INPUT_NORMAL; 421 | horswp_window(); 422 | rebuild_reference(); 423 | search(newpat); 424 | break; 425 | default: 426 | { 427 | /* if a line was selected */ 428 | const int cc = dispchar2int(c); 429 | if(cc != -1 && cc < totallines) { 430 | change[cc] = !change[cc]; 431 | window_change |= CH_RESULT; 432 | } 433 | } 434 | } 435 | 436 | return 0; 437 | } 438 | 439 | // XXX: move this 440 | int changestring(const char *from, const char *to, const bool *const change, const int change_len) { 441 | char newfile[PATHLEN + 1]; /* new file name */ 442 | char oldfile[PATHLEN + 1]; /* old file name */ 443 | char linenum[NUMLEN + 1]; /* file line number */ 444 | char msg[MSGLEN + 1]; /* message */ 445 | FILE *script; /* shell script file */ 446 | 447 | 448 | // Return early 449 | bool anymarked = false; /* any line marked */ 450 | for(int i = 0; i < change_len; i++) { 451 | if(change[i]) { 452 | anymarked = true; 453 | break; 454 | } 455 | } 456 | if(!anymarked) { return false; } 457 | 458 | /* open the temporary file */ 459 | if((script = myfopen(temp2, "w")) == NULL) { 460 | cannotopen(temp2); 461 | return (false); 462 | } 463 | 464 | /* for each line containing the old text */ 465 | fprintf(script, "ed - <<\\!\n"); 466 | *oldfile = '\0'; 467 | fseek(refsfound, 0, SEEK_SET); 468 | for(int i = 0; fscanf(refsfound, 469 | "%" PATHLEN_STR "s%*s%" NUMLEN_STR "s%*[^\n]", 470 | newfile, 471 | linenum) == 2; 472 | ++i) { 473 | /* see if the line is to be changed */ 474 | if(!change[i]) { break; } 475 | 476 | /* if this is a new file */ 477 | if(strcmp(newfile, oldfile) != 0) { 478 | 479 | /* make sure it can be changed */ 480 | if(access(newfile, WRITE) != 0) { 481 | snprintf(msg, sizeof(msg), "Cannot write to file %s", newfile); 482 | postmsg(msg); 483 | goto end; 484 | } 485 | /* if there was an old file */ 486 | if(*oldfile != '\0') { fprintf(script, "w\n"); /* save it */ } 487 | /* edit the new file */ 488 | strcpy(oldfile, newfile); 489 | fprintf(script, "e %s\n", oldfile); 490 | } 491 | /* output substitute command */ 492 | fprintf(script, "%ss/", linenum); /* change */ 493 | for(const char *s = from; *s != '\0'; ++s) { 494 | /* old text */ 495 | if(strchr("/\\[.^*", *s) != NULL) { putc('\\', script); } 496 | if(caseless == true && isalpha((unsigned char)*s)) { 497 | putc('[', script); 498 | if(islower((unsigned char)*s)) { 499 | putc(toupper((unsigned char)*s), script); 500 | putc(*s, script); 501 | } else { 502 | putc(*s, script); 503 | putc(tolower((unsigned char)*s), script); 504 | } 505 | putc(']', script); 506 | } else { 507 | putc(*s, script); 508 | } 509 | } 510 | putc('/', script); /* to */ 511 | for(const char *s = to; *s != '\0'; ++s) { /* new text */ 512 | if(strchr("/\\&", *s) != NULL) { putc('\\', script); } 513 | putc(*s, script); 514 | } 515 | fprintf(script, "/gp\n"); /* and print */ 516 | } 517 | fprintf(script, "w\nq\n!\n"); /* write and quit */ 518 | fflush(script); 519 | 520 | /* edit the files */ 521 | execute("sh", "sh", temp2, NULL); // XXX: this should not echo 522 | end: 523 | fclose(script); 524 | return true; 525 | } 526 | 527 | int handle_input(const int c) { 528 | /* - was wating for any input - */ 529 | if(do_press_any_key) { 530 | do_press_any_key = false; 531 | return 0; 532 | } 533 | /* - Resize - */ 534 | /* it's treated specially here because curses treat it specially: 535 | + its valid without keypad() 536 | + as far as i can tell this is the only key that does not 537 | flush after itself 538 | */ 539 | if(c == KEY_RESIZE) { 540 | redisplay(); 541 | flushinp(); 542 | return 0; 543 | } 544 | 545 | /* --- global --- */ 546 | const int r = global_input(c); 547 | if(r) { return 0; } 548 | /* --- mode specific --- */ 549 | switch(input_mode) { 550 | case INPUT_NORMAL: 551 | const int r = normal_global_input(c); 552 | if(r) { return 0; } 553 | // 554 | if(*current_window == winput) { 555 | return interpret(c); 556 | } else if(*current_window == wmode) { 557 | return wmode_input(c); 558 | } else if(*current_window == wresult) { 559 | return wresult_input(c); 560 | } 561 | assert("'current_window' dangling."); 562 | break; /* NOTREACHED */ 563 | case INPUT_CHANGE_TO: 564 | case INPUT_APPEND: 565 | case INPUT_READ: 566 | return interpret(c); 567 | case INPUT_CHANGE: 568 | return change_input(c); 569 | } 570 | 571 | return 0; 572 | } 573 | -------------------------------------------------------------------------------- /source/invlib.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | #ifndef CSCOPE_INVLIB_H 34 | #define CSCOPE_INVLIB_H 35 | 36 | #include /* need definition of FILE* */ 37 | #include /* need definition of CHAR_MAX */ 38 | 39 | /* inverted index definitions */ 40 | 41 | /* postings temporary file long number coding into characters */ 42 | #if CHAR_MAX == 255 43 | # define BASE 223 /* 255 - ' ' */ 44 | # define PRECISION 4 /* maximum digits after converting a long */ 45 | #else 46 | # if CHAR_MAX == 127 /* assume sign-extension of a char when converted to an int */ 47 | # define BASE 95 /* 127 - ' ' */ 48 | # define PRECISION 5 /* maximum digits after converting a long */ 49 | # else 50 | # error Need a platform with 8 bits in a char value 51 | # endif 52 | #endif 53 | 54 | /* inverted index access parameters */ 55 | #define INVAVAIL 0 56 | #define INVBUSY 1 57 | #define INVALONE 2 58 | 59 | /* boolean set operations */ 60 | #define bool_OR 3 61 | #define AND 4 62 | #define falseT 5 63 | #define REVERSEfalseT 6 64 | 65 | /* note that the entire first block is for parameters */ 66 | typedef struct { 67 | long version; /* inverted index format version */ 68 | long filestat; /* file status word */ 69 | long sizeblk; /* size of logical block in bytes */ 70 | long startbyte; /* first byte of superfinger */ 71 | long supsize; /* size of superfinger in bytes */ 72 | long cntlsize; /* size of max cntl space (should be a multiple of BUFSIZ) */ 73 | long share; /* flag whether to use shared memory */ 74 | } PARAM; 75 | 76 | typedef struct { 77 | FILE *invfile; /* the inverted file ptr */ 78 | FILE *postfile; /* posting file ptr */ 79 | PARAM param; /* control parameters for the file */ 80 | char *iindex; /* ptr to space for superindex */ 81 | union logicalblk *logblk; /* ptr to space for a logical block */ 82 | long numblk; /* number of block presently at *logblk */ 83 | long keypnt; /* number item in present block found */ 84 | } INVCONTROL; 85 | 86 | typedef struct { 87 | short offset; /* offset in this logical block */ 88 | unsigned char size; /* size of term */ 89 | unsigned char space; /* number of longs of growth space */ 90 | long post; /* number of postings for this entry */ 91 | } ENTRY; 92 | 93 | typedef struct { 94 | long lineoffset; /* source line database offset */ 95 | long fcnoffset; /* function name database offset */ 96 | long fileindex : 24; /* source file name index */ 97 | long type : 8; /* reference type (mark character) */ 98 | } POSTING; 99 | 100 | extern long *srcoffset; /* source file name database offsets */ 101 | extern int nsrcoffset; /* number of file name database offsets */ 102 | 103 | 104 | void boolclear(void); 105 | POSTING *boolfile(INVCONTROL *invcntl, long *num, int boolarg); 106 | void invclose(INVCONTROL *invcntl); 107 | void invdump(INVCONTROL *invcntl, char *term); 108 | long invfind(INVCONTROL *invcntl, char *searchterm); 109 | int invforward(INVCONTROL *invcntl); 110 | int invopen(INVCONTROL *invcntl, char *invname, char *invpost, int status); 111 | long invmake(char *invname, char *invpost, FILE *infile); 112 | long invterm(INVCONTROL *invcntl, char *term); 113 | 114 | #endif /* CSCOPE_INVLIB_H */ 115 | -------------------------------------------------------------------------------- /source/keys.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYS_H 2 | #define KEYS_H 3 | 4 | #include 5 | 6 | /* Key macros */ 7 | /* These macros are not guaranteed to be defined, 8 | * however we wish to test for these anyways while 9 | * interpretting user commands. 10 | * Input values are guaranteed to be postive, 11 | * so setting them to -1 means the test always just silently fail, 12 | * but compile when the they are not supported means of input. 13 | */ 14 | #define KEY_UNDEF_BASE 0 15 | 16 | #ifndef KEY_DOWN 17 | # define KEY_DOWN KEY_UNDEF_BASE - 1 18 | #endif 19 | #ifndef KEY_UP 20 | # define KEY_UP KEY_UNDEF_BASE - 2 21 | #endif 22 | #ifndef KEY_LEFT 23 | # define KEY_LEFT KEY_UNDEF_BASE - 3 24 | #endif 25 | #ifndef KEY_RIGHT 26 | # define KEY_RIGHT KEY_UNDEF_BASE - 4 27 | #endif 28 | #ifndef KEY_HOME 29 | # define KEY_HOME _KEY_UNDEF_BASE - 5 30 | #endif 31 | #ifndef KEY_LL 32 | # define KEY_LL KEY_UNDEF_BASE - 6 33 | #endif 34 | #ifndef KEY_PPAGE 35 | # define KEY_PPAGE KEY_UNDEF_BASE - 7 36 | #endif 37 | #ifndef KEY_NPAGE 38 | # define KEY_NPAGE KEY_UNDEF_BASE - 8 39 | #endif 40 | #ifndef KEY_ENTER 41 | # define KEY_ENTER KEY_UNDEF_BASE - 9 42 | #endif 43 | #ifndef KEY_CLEAR 44 | # define KEY_CLEAR KEY_UNDEF_BASE - 10 45 | #endif 46 | #ifndef KEY_RESIZE 47 | # define KEY_RESIZE KEY_UNDEF_BASE - 11 48 | #endif 49 | #ifndef KEY_END 50 | # define KEY_END KEY_UNDEF_BASE - 12 51 | #endif 52 | 53 | /* Always define these keys */ 54 | #ifndef ESC 55 | # define ESC '\033' /* escape character */ 56 | #endif 57 | #ifndef DEL 58 | # define DEL '\177' /* delete character */ 59 | #endif 60 | 61 | 62 | #endif /* KEYS_H*/ 63 | -------------------------------------------------------------------------------- /source/library.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | #ifndef CSCOPE_LIBRARY_H 34 | #define CSCOPE_LIBRARY_H 35 | 36 | #include /* need FILE* type def. */ 37 | 38 | /* private library */ 39 | char *compress_path(const char *pathname_); 40 | char *egrepinit(const char *egreppat); 41 | char *logdir(char *name); 42 | const char *basename(const char *path); 43 | FILE *myfopen(const char * path, const char * mode); 44 | int myopen(const char * path, int flag, int mode); 45 | FILE *mypopen(char *cmd, char *mode); 46 | int mypclose(FILE *ptr); 47 | void egrepcaseless(int i); 48 | 49 | #endif /* CSCOPE_LIBRARY_H */ 50 | -------------------------------------------------------------------------------- /source/lookup.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * keyword look-up routine for the C symbol scanner 36 | */ 37 | 38 | #include "global.h" 39 | #include "lookup.h" 40 | 41 | /* keyword text for fast testing of keywords in the scanner */ 42 | const char enumtext[] = "enum"; 43 | const char externtext[] = "extern"; 44 | const char structtext[] = "struct"; 45 | const char typedeftext[] = "typedef"; 46 | const char uniontext[] = "union"; 47 | 48 | /* This keyword table is also used for keyword text compression. Keywords 49 | * with an index less than the numeric value of a space are replaced with the 50 | * control character corresponding to the index, so they cannot be moved 51 | * without changing the database file version and adding compatibility code 52 | * for old databases. 53 | */ 54 | struct keystruct keyword[] = { 55 | {"", '\0', NULL}, /* dummy entry */ 56 | {"#define", ' ', NULL}, /* must be table entry 1 */ 57 | {"#include", ' ', NULL}, /* must be table entry 2 */ 58 | {"break", '\0', NULL}, /* rarely in cross-reference */ 59 | {"case", ' ', NULL}, 60 | {"char", ' ', NULL}, 61 | {"continue", '\0', NULL}, /* rarely in cross-reference */ 62 | {"default", '\0', NULL}, /* rarely in cross-reference */ 63 | {"double", ' ', NULL}, 64 | {"\t", '\0', NULL}, /* must be the table entry 9 */ 65 | {"\n", '\0', NULL}, /* must be the table entry 10 */ 66 | {"else", ' ', NULL}, 67 | {enumtext, ' ', NULL}, 68 | {externtext, ' ', NULL}, 69 | {"float", ' ', NULL}, 70 | {"for", '(', NULL}, 71 | {"goto", ' ', NULL}, 72 | {"if", '(', NULL}, 73 | {"int", ' ', NULL}, 74 | {"long", ' ', NULL}, 75 | {"register", ' ', NULL}, 76 | {"return", '\0', NULL}, 77 | {"short", ' ', NULL}, 78 | {"sizeof", '\0', NULL}, 79 | {"static", ' ', NULL}, 80 | {structtext, ' ', NULL}, 81 | {"switch", '(', NULL}, 82 | {typedeftext, ' ', NULL}, 83 | {uniontext, ' ', NULL}, 84 | {"unsigned", ' ', NULL}, 85 | {"void", ' ', NULL}, 86 | {"while", '(', NULL}, 87 | 88 | /* these keywords are not compressed */ 89 | {"do", '\0', NULL}, 90 | {"auto", ' ', NULL}, 91 | {"fortran", ' ', NULL}, 92 | {"const", ' ', NULL}, 93 | {"signed", ' ', NULL}, 94 | {"volatile", ' ', NULL}, 95 | }; 96 | #define KEYWORDS (sizeof(keyword) / sizeof(keyword[0])) 97 | 98 | #define HASHMOD (KEYWORDS * 2 + 1) 99 | 100 | static struct keystruct *hashtab[HASHMOD]; /* pointer table */ 101 | 102 | /* put the keywords into the symbol table */ 103 | void initsymtab(void) { 104 | for(unsigned i = 1; i < KEYWORDS; i++) { 105 | struct keystruct *p = keyword + i; 106 | int j = hash(p->text) % HASHMOD; 107 | p->next = hashtab[j]; 108 | hashtab[j] = p; 109 | } 110 | } 111 | 112 | /* see if this identifier is a keyword */ 113 | char * lookup(char *ident, bool do_compressed) { 114 | struct keystruct *p; 115 | int c; 116 | 117 | /* look up the identifier in the keyword table */ 118 | for(p = hashtab[hash(ident) % HASHMOD]; p != NULL; p = p->next) { 119 | if(strequal(ident, p->text)) { 120 | if(compress == true && (c = p - keyword) < ' ') { 121 | ident[0] = c; /* compress the keyword */ 122 | } 123 | return (p->text); 124 | } 125 | } 126 | /* this is an identifier */ 127 | return NULL; 128 | } 129 | 130 | /* form hash value for string */ 131 | int hash(const char * ss) { 132 | int i = 0; 133 | unsigned char *s = (unsigned char *)ss; 134 | 135 | while (*s != '\0') { 136 | i += *s++; /* += is faster than <<= for cscope */ 137 | 138 | } 139 | 140 | return (i); 141 | } 142 | -------------------------------------------------------------------------------- /source/lookup.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 2001, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | #ifndef CSCOPE_LOOKUP_H 34 | #define CSCOPE_LOOKUP_H 35 | 36 | /* declarations for objects defined in lookup.c */ 37 | 38 | /* keyword text for fast testing of keywords in the scanner */ 39 | extern const char enumtext[]; 40 | extern const char externtext[]; 41 | extern const char structtext[]; 42 | extern const char typedeftext[]; 43 | extern const char uniontext[]; 44 | 45 | #endif /* CSCOPE_LOOKUP_H */ 46 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | 34 | /* cscope - interactive C symbol cross-reference 35 | * 36 | * main functions 37 | */ 38 | 39 | #include "global.h" 40 | 41 | #include "build.h" 42 | #include "vpath.h" 43 | #include "version.inc" 44 | #include "scanner.h" 45 | 46 | #include /* atoi */ 47 | #include 48 | #include /* needed by stat.h */ 49 | #include /* stat */ 50 | #include 51 | #include 52 | 53 | /* note: these digraph character frequencies were calculated from possible 54 | printable digraphs in the cross-reference for the C compiler */ 55 | char dichar1[] = " teisaprnl(of)=c"; /* 16 most frequent first chars */ 56 | char dichar2[] = " tnerpla"; /* 8 most frequent second chars 57 | using the above as first chars */ 58 | char dicode1[256]; /* digraph first character code */ 59 | char dicode2[256]; /* digraph second character code */ 60 | 61 | bool compress = true; /* compress the characters in the crossref */ 62 | bool dbtruncated; /* database symbols are truncated to 8 chars */ 63 | int dispcomponents = 1; /* file path components to display */ 64 | bool editallprompt = true; /* prompt between editing files */ 65 | int fileversion; /* cross-reference file version */ 66 | bool incurses = false; /* in curses */ 67 | char *prependpath; /* prepend path to file names */ 68 | FILE *refsfound; /* references found file */ 69 | long totalterms; /* total inverted index terms */ 70 | bool trun_syms; /* truncate symbols to 8 characters */ 71 | char tempstring[TEMPSTRING_LEN + 1]; /* use this as a buffer, instead of 'yytext', 72 | * which had better be left alone 73 | */ 74 | const char * const * fileargv; /* file argument values */ 75 | 76 | static char path[PATHLEN + 1]; /* file path */ 77 | 78 | /* Internal prototypes: */ 79 | static void skiplist(FILE *oldrefs); 80 | static void initcompress(void); 81 | static inline void linemode_event_loop(void); 82 | static inline void screenmode_event_loop(void); 83 | 84 | static void read_old_reffile(const char * reffile); 85 | 86 | 87 | static inline 88 | void siginit(void) { 89 | /* if running in the foreground */ 90 | if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 91 | /* cleanup on the interrupt and quit signals */ 92 | signal(SIGINT, myexit); 93 | signal(SIGQUIT, myexit); 94 | } 95 | 96 | signal(SIGHUP, myexit); 97 | signal(SIGTERM, myexit); 98 | 99 | /* ignore PIPE signal, so myexit() will have a chance to clean up in 100 | * linemode, while in curses mode the "|" command can cause a pipe signal 101 | * too 102 | */ 103 | signal(SIGPIPE, SIG_IGN); 104 | 105 | //if (linemode == false) { signal(SIGWINCH, redisplay); } 106 | } 107 | 108 | void cannotopen(const char *const file) { 109 | posterr("Cannot open file %s", file); 110 | } 111 | 112 | void cannotwrite(const char * const file) { 113 | unlink(file); 114 | 115 | postfatal("Removed file %s because write failed", file); 116 | } 117 | 118 | /* set up the digraph character tables for text compression */ 119 | static 120 | void initcompress(void) { 121 | if (compress == true) { 122 | for (int i = 0; i < 16; i++) { 123 | dicode1[(unsigned char)(dichar1[i])] = i * 8 + 1; 124 | } 125 | for (int i = 0; i < 8; i++) { 126 | dicode2[(unsigned char)(dichar2[i])] = i + 1; 127 | } 128 | } 129 | } 130 | 131 | /* skip the list in the cross-reference file */ 132 | static 133 | void skiplist(FILE *oldrefs) { 134 | int i; 135 | 136 | if (fscanf(oldrefs, "%d", &i) != 1) { 137 | postfatal(PROGRAM_NAME ": cannot read list size from file %s\n", reffile); 138 | } 139 | while(--i >= 0) { 140 | if (fscanf(oldrefs, "%*s") != 0) { 141 | postfatal(PROGRAM_NAME ": cannot read list name from file %s\n", reffile); 142 | } 143 | } 144 | } 145 | 146 | /* cleanup and exit */ 147 | void myexit(int sig) { 148 | /* Close file before unlinking it. DOS absolutely needs it */ 149 | if (refsfound != NULL) { fclose(refsfound); } 150 | 151 | deinit_temp_files(); 152 | 153 | /* restore the terminal to its original mode */ 154 | if (incurses == true) { exitcurses(); } 155 | /* dump core for debugging on the quit signal */ 156 | if (sig == SIGQUIT) { abort(); } 157 | /* HBB 20000421: be nice: free allocated data */ 158 | freefilelist(); 159 | freeinclist(); 160 | freesrclist(); 161 | freecrossref(); 162 | free_newbuildfiles(); 163 | 164 | if (remove_symfile_onexit == true) { 165 | unlink(reffile); 166 | unlink(invname); 167 | unlink(invpost); 168 | } 169 | 170 | exit(sig); 171 | } 172 | 173 | 174 | /* Remove a singular newline from the end of a string (if any). */ 175 | static inline 176 | void remove_trailing_newline(char *buf, size_t len) { 177 | 178 | if ((len > 0) && 179 | (buf[len - 1] == '\n')) { 180 | buf[len - 1] = '\0'; 181 | } 182 | } 183 | 184 | static inline 185 | void linemode_event_loop(void) { 186 | if (*input_line != '\0') { /* do any optional search */ 187 | 188 | if (search(input_line) == true) { 189 | 190 | /* print the total number of lines in verbose mode */ 191 | if (verbosemode == true) { 192 | printf(PROGRAM_NAME ": %d lines\n", totallines); 193 | } 194 | 195 | int c = getc(refsfound); 196 | while(c != EOF) { 197 | putchar(c); 198 | c = getc(refsfound); 199 | } 200 | } 201 | } 202 | 203 | if (onesearch == true) { 204 | myexit(0); 205 | } 206 | 207 | for (char *s;;) { 208 | char buf[PATLEN + 2]; 209 | 210 | printf(">> "); 211 | fflush(stdout); 212 | if (fgets(buf, sizeof(buf), stdin) == NULL) { myexit(0); } 213 | /* remove any trailing newline character */ 214 | remove_trailing_newline(buf, strlen(buf)); 215 | 216 | switch (*buf) { 217 | case ASCII_DIGIT: 218 | field = *buf - '0'; 219 | strcpy(input_line, buf + 1); 220 | if (search(input_line) == false) { 221 | printf("Unable to search database\n"); 222 | } else { 223 | printf("cscope: %d lines\n", totallines); 224 | int c; 225 | while((c = getc(refsfound)) != EOF) { 226 | putchar(c); 227 | } 228 | } 229 | break; 230 | 231 | case 'c': /* toggle caseless mode */ 232 | case ctrl('C'): 233 | /* 27-11-2024 20:42 yama XXX: The logic works but I am unable 234 | to test functionality in the terminal? */ 235 | caseless = !(caseless); 236 | egrepcaseless(caseless); 237 | break; 238 | 239 | case 'r': /* rebuild database cscope style */ 240 | case ctrl('R'): 241 | freefilelist(); 242 | makefilelist(fileargv); 243 | /* FALLTHROUGH */ 244 | 245 | case 'R': /* rebuild database samuel style */ 246 | rebuild(); 247 | putchar('\n'); 248 | break; 249 | 250 | case 'C': /* clear file names */ 251 | freefilelist(); 252 | putchar('\n'); 253 | break; 254 | 255 | case 'F': /* add a file name */ 256 | strcpy(path, buf + 1); 257 | if (infilelist(path) == false && (s = inviewpath(path)) != NULL) { 258 | addsrcfile(s); 259 | } 260 | putchar('\n'); 261 | break; 262 | 263 | case 'q': /* quit */ 264 | case ctrl('D'): 265 | case ctrl('Z'): 266 | myexit(0); 267 | /* NOTREACHED */ 268 | break; 269 | default: 270 | fprintf(stderr, PROGRAM_NAME ": unknown command '%s'\n", buf); 271 | break; 272 | } 273 | } 274 | } 275 | 276 | static inline 277 | void screenmode_event_loop(void) { 278 | /* pause before clearing the screen if there have been error messages */ 279 | if (errorsfound == true) { 280 | errorsfound = false; 281 | askforreturn(); 282 | } 283 | /* do any optional search */ 284 | if (*input_line != '\0') { 285 | // command(ctrl('Y')); /* search */ // XXX: fix 286 | } else if (reflines != NULL) { 287 | /* read any symbol reference lines file */ 288 | readrefs(reflines); 289 | } 290 | 291 | for (;;) { 292 | display(); 293 | handle_input(wgetch(stdscr)); // NOTE: getch() does not return KEY_* codes 294 | } 295 | } 296 | 297 | static 298 | void read_old_reffile(const char * reffile) { 299 | char * s; 300 | FILE * names; /* name file pointer */ 301 | int oldnum; /* number in old cross-ref */ 302 | FILE * oldrefs = vpfopen(reffile, "rb"); /* old cross-reference file */ 303 | if (!oldrefs) { 304 | postfatal(PROGRAM_NAME ": cannot open file %s\n", reffile); 305 | } 306 | 307 | /* get the crossref file version but skip the current directory */ 308 | if (fscanf(oldrefs, PROGRAM_NAME " %d %*s", &fileversion) != 1) { 309 | postfatal(PROGRAM_NAME ": cannot read file version from file %s\n", reffile); 310 | } 311 | if (fileversion >= 8) { 312 | 313 | /* override these command line options */ 314 | compress = true; 315 | invertedindex = false; 316 | 317 | /* see if there are options in the database */ 318 | for (int c;;) { 319 | getc(oldrefs); /* skip the blank */ 320 | if ((c = getc(oldrefs)) != '-') { 321 | ungetc(c, oldrefs); 322 | break; 323 | } 324 | switch (getc(oldrefs)) { 325 | case 'c': /* ASCII characters only */ 326 | compress = false; 327 | break; 328 | case 'q': /* quick search */ 329 | invertedindex = true; 330 | fscanf(oldrefs, "%ld", &totalterms); 331 | break; 332 | case 'T': /* truncate symbols to 8 characters */ 333 | dbtruncated = true; 334 | trun_syms = true; 335 | break; 336 | } 337 | } 338 | initcompress(); 339 | seek_to_trailer(oldrefs); 340 | } 341 | /* skip the source and include directory lists */ 342 | skiplist(oldrefs); 343 | skiplist(oldrefs); 344 | 345 | /* get the number of source files */ 346 | if (fscanf(oldrefs, "%lu", &nsrcfiles) != 1) { 347 | postfatal( 348 | PROGRAM_NAME ": cannot read source file size from file %s\n", 349 | reffile 350 | ); 351 | } 352 | /* get the source file list */ 353 | srcfiles = malloc(nsrcfiles * sizeof(*srcfiles)); 354 | if (fileversion >= 9) { 355 | 356 | /* allocate the string space */ 357 | if (fscanf(oldrefs, "%d", &oldnum) != 1) { 358 | postfatal( 359 | PROGRAM_NAME ": cannot read string space size from file %s\n", 360 | reffile 361 | ); 362 | } 363 | s = malloc(oldnum); 364 | getc(oldrefs); /* skip the newline */ 365 | 366 | /* read the strings */ 367 | if (fread(s, oldnum, 1, oldrefs) != 1) { 368 | postfatal( 369 | PROGRAM_NAME ": cannot read source file names from file %s\n", 370 | reffile 371 | ); 372 | } 373 | /* change newlines to nulls */ 374 | for (int i = 0; i < nsrcfiles; i++) { 375 | srcfiles[i] = s; 376 | for (++s; *s != '\n'; ++s) { ; } 377 | *s = '\0'; 378 | ++s; 379 | } 380 | /* if there is a file of source file names */ 381 | if ((namefile != NULL && (names = vpfopen(namefile, "r")) != NULL) 382 | || (names = vpfopen(NAMEFILE, "r")) != NULL) { 383 | /* read any -p option from it */ 384 | while(fgets(path, sizeof(path), names) != NULL && *path == '-') { 385 | char orig_path1 = path[1]; 386 | s = path + 2; /* for "-Ipath" */ 387 | if (*s == '\0') { /* if "-I path" */ 388 | fgets(path, sizeof(path), names); 389 | s = path; 390 | } 391 | switch (orig_path1) { 392 | case 'p': /* file path components to display */ 393 | if (*s < '0' || *s > '9') { 394 | posterr( 395 | PROGRAM_NAME ": -p option in file %s: missing or invalid numeric value\n", 396 | namefile 397 | ); 398 | } 399 | dispcomponents = atoi(s); 400 | } 401 | } 402 | fclose(names); 403 | } 404 | } else { 405 | for (int i = 0; i < nsrcfiles; ++i) { 406 | if (!fgets(path, sizeof(path), oldrefs)) { 407 | postfatal(PROGRAM_NAME 408 | ": cannot read source file name from file %s\n", 409 | reffile); 410 | /* NOTREACHED */ 411 | } 412 | srcfiles[i] = strdup(path); 413 | } 414 | } 415 | fclose(oldrefs); 416 | } 417 | 418 | int main(const int argc, const char * const * const argv) { 419 | 420 | yyin = stdin; 421 | yyout = stdout; 422 | 423 | fileargv = (const char*const*)parse_options(argc, argv); 424 | 425 | /* NOTE: the envirnment under no condition can overwrite cli set variables 426 | */ 427 | readenv(preserve_database); 428 | 429 | /* XXX */ 430 | init_temp_files(); 431 | 432 | /* if the database path is relative and it can't be created */ 433 | if (reffile[0] != '/' 434 | && access(".", WRITE) != 0) { 435 | /* put it in the home directory if the database may not be 436 | * up-to-date or doesn't exist in the relative directory, 437 | * so a database in the current directory will be 438 | * used instead of failing to open a non-existant database in 439 | * the home directory 440 | */ 441 | snprintf(path, sizeof(path), "%s/%s", home, reffile); 442 | if (preserve_database == false 443 | || access(path, READ) == 0) { 444 | reffile = strdup(path); 445 | snprintf(path, sizeof(path), "%s/%s", home, invname); 446 | invname = strdup(path); 447 | snprintf(path, sizeof(path), "%s/%s", home, invpost); 448 | invpost = strdup(path); 449 | } 450 | } 451 | 452 | siginit(); 453 | 454 | if (linemode == false) { 455 | dispinit(); /* initialize display parameters */ 456 | postmsg(""); /* clear any build progress message */ 457 | display(); /* display the version number and input fields */ 458 | } 459 | 460 | 461 | /* if the cross-reference is to be considered up-to-date */ 462 | if (preserve_database == true) { 463 | read_old_reffile(reffile); 464 | } else { 465 | /* make the source file list */ 466 | srcfiles = malloc(msrcfiles * sizeof(*srcfiles)); 467 | makefilelist(fileargv); 468 | if (nsrcfiles == 0) { 469 | postfatal(PROGRAM_NAME ": no source files found\n"); 470 | } 471 | 472 | /* add /usr/include to the #include directory list, 473 | but not in kernelmode... kernels tend not to use it. */ 474 | if (!kernelmode) { 475 | includedir(incdir); 476 | } 477 | 478 | /* initialize the C keyword table */ 479 | initsymtab(); 480 | 481 | /* Tell build.c about the filenames to create: */ 482 | setup_build_filenames(reffile); 483 | 484 | /* build the cross-reference */ 485 | initcompress(); 486 | if (linemode == false 487 | || verbosemode == true) { /* display if verbose as well */ 488 | postmsg("Building cross-reference..."); 489 | } 490 | build(); 491 | if (linemode == false) { postmsg(""); /* clear any build progress message */ } 492 | if (buildonly == true) { 493 | myexit(0); 494 | } 495 | } 496 | 497 | opendatabase(reffile); 498 | 499 | if (linemode == true) { 500 | /* if using the line oriented user interface so cscope can be a 501 | subprocess to emacs or samuel */ 502 | linemode_event_loop(); 503 | } else { 504 | screenmode_event_loop(); 505 | } 506 | 507 | return 0; 508 | } 509 | -------------------------------------------------------------------------------- /source/mouse.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * mouse functions 36 | */ 37 | 38 | /* NOTE: the mouse functionallity has been void of anyone, 39 | * but those on the most esoteric of systems 40 | * for the past 20 years. 41 | * as of now, non-of the code here should ever execute 42 | * this file will be kept here as a reference for a 43 | * future complete rewrite of mouse support 44 | */ 45 | 46 | void mousemenu(void); 47 | void mouseinit(void); 48 | void mousereinit(void); 49 | 50 | typedef struct { /* mouse action */ 51 | int button; 52 | int percent; 53 | int x1; 54 | int y1; 55 | int x2; 56 | int y2; 57 | } MOUSE; 58 | 59 | MOUSE *getmouseaction(char leading_char); 60 | 61 | // extern bool unixpcmouse; /* UNIX PC mouse interface */ 62 | 63 | extern int LINES; 64 | 65 | #define FLDLINE (LINES - FIELDS - 1 - 1) /* first input field line */ 66 | 67 | #include "global.h" 68 | 69 | #include 70 | 71 | bool mouse = false; /* mouse interface */ 72 | 73 | #ifdef UNIXPC /* build command requires #ifdef instead of #if */ 74 | # include 75 | bool unixpcmouse = false; /* running with a mouse on the Unix PC? */ 76 | static int uw_hs, uw_vs; /* character height and width */ 77 | #endif 78 | 79 | typedef struct { /* menu */ 80 | char *text; 81 | char *value; 82 | } MENU; 83 | 84 | static MENU mainmenu[] = { 85 | /* main menu */ 86 | {"Send", "##\033s##\r"}, 87 | {"Repeat", "\031" }, 88 | {"Edit All", "\05" }, 89 | {"Rebuild", "\022" }, 90 | {"Shell", "!" }, 91 | {"Redraw", "\f" }, 92 | {"Help", "?" }, 93 | {"Exit", "\04" }, 94 | {NULL, NULL } 95 | }; 96 | 97 | static MENU changemenu[] = { 98 | /* change mode menu */ 99 | {"Mark Screen", "*" }, 100 | {"Mark All", "a" }, 101 | {"Change", "\04" }, 102 | {"No Change", "\033"}, 103 | {"Shell", "!" }, 104 | {"Redraw", "\f" }, 105 | {"Help", "?" }, 106 | {NULL, NULL } 107 | }; 108 | 109 | static MENU *loaded; /* menu loaded */ 110 | static bool emacsviterm = false; /* terminal type */ 111 | 112 | static void loadmenu(MENU *menu); 113 | static int getcoordinate(void); 114 | static int getpercent(void); 115 | 116 | /* see if there is a mouse interface */ 117 | void mouseinit(void) { 118 | char *term = ""; // mygetenv("TERM", ""); // NOTE: this function no longer exists 119 | 120 | /* see if this is emacsterm or viterm */ 121 | if(strcmp(term, "emacsterm") == 0 || strcmp(term, "viterm") == 0) { 122 | emacsviterm = true; 123 | mouse = true; 124 | } 125 | /* the MOUSE enviroment variable is for 5620 terminal programs that have 126 | mouse support but the TERM environment variable is the same as a 127 | terminal without a mouse, such as myx */ 128 | else if(strcmp("" /* XXX mygetenv("MOUSE", "")*/, "myx") == 0) { 129 | mouse = true; 130 | } 131 | #if UNIXPC 132 | else if(strcmp(term, "s4") == 0 || strcmp(term, "s120") == 0 || 133 | strcmp(term, "s90") == 0) { 134 | int retval; 135 | struct uwdata uwd; /* Window data structure */ 136 | struct umdata umd; /* Mouse data structure */ 137 | 138 | /* Ask for character size info */ 139 | 140 | retval = ioctl(1, WIOCGETD, &uwd); 141 | if(retval || uwd.uw_hs <= 0 || uwd.uw_vs <= 0) { 142 | /************************************************** 143 | * something wrong with the kernel, so fake it... 144 | **************************************************/ 145 | if(!strcmp(term, "s4")) { 146 | uw_hs = 9; 147 | uw_vs = 12; 148 | } else { 149 | uw_hs = 6; 150 | uw_vs = 10; 151 | } 152 | } else { 153 | /* Kernel is working and knows about this font */ 154 | uw_hs = uwd.uw_hs; 155 | uw_vs = uwd.uw_vs; 156 | } 157 | 158 | /************************************************** 159 | * Now turn on mouse reporting so we can actually 160 | * make use of all this stuff. 161 | **************************************************/ 162 | if((retval = ioctl(1, WIOCGETMOUSE, &umd)) != -1) { 163 | umd.um_flags = MSDOWN + MSUP; 164 | ioctl(1, WIOCSETMOUSE, &umd); 165 | } 166 | unixpcmouse = true; 167 | } 168 | #endif 169 | if(mouse == true) { loadmenu(mainmenu); } 170 | } 171 | 172 | /* load the correct mouse menu */ 173 | void mousemenu(void) { 174 | if(mouse == true) { 175 | if(input_mode == INPUT_CHANGE) { 176 | loadmenu(changemenu); 177 | } else { 178 | loadmenu(mainmenu); 179 | } 180 | } 181 | } 182 | 183 | /* download a menu */ 184 | static void loadmenu(MENU *menu) { 185 | int i; 186 | 187 | if(emacsviterm == true) { 188 | mousereinit(); 189 | (void)printf("\033V1"); /* display the scrollbar */ 190 | (void)printf("\033M0@%s@%s@", menu[0].text, menu[0].value); 191 | for(i = 1; menu[i].text != NULL; ++i) { 192 | (void)printf("\033M@%s@%s@", menu[i].text, menu[i].value); 193 | } 194 | } else { /* myx */ 195 | int len; 196 | 197 | mousecleanup(); 198 | (void)printf("\033[6;1X\033[9;1X"); 199 | for(i = 0; menu[i].text != NULL; ++i) { 200 | len = strlen(menu[i].text); 201 | (void)printf("\033[%d;%dx%s%s", 202 | len, 203 | (int)(len + strlen(menu[i].value)), 204 | menu[i].text, 205 | menu[i].value); 206 | } 207 | loaded = menu; 208 | } 209 | (void)fflush(stdout); 210 | } 211 | 212 | /* reinitialize the mouse in case curses changed the attributes */ 213 | void mousereinit(void) { 214 | if(emacsviterm == true) { 215 | 216 | /* enable the mouse click and sweep coordinate control sequence */ 217 | /* and switch to menu 2 */ 218 | (void)printf("\033{2\033#2"); 219 | (void)fflush(stdout); 220 | } 221 | } 222 | 223 | /* restore the mouse attributes */ 224 | void mousecleanup(void) { 225 | int i; 226 | 227 | if(loaded != NULL) { /* only true for myx */ 228 | 229 | /* remove the mouse menu */ 230 | (void)printf("\033[6;0X\033[9;0X"); 231 | for(i = 0; loaded[i].text != NULL; ++i) { 232 | (void)printf("\033[0;0x"); 233 | } 234 | loaded = NULL; 235 | } 236 | } 237 | 238 | /* draw the scrollbar */ 239 | void drawscrollbar(int top, int bot) { 240 | int p1, p2; 241 | 242 | if(emacsviterm == true) { 243 | if(bot > top) { 244 | p1 = 16 + (top - 1) * 100 / totallines; 245 | p2 = 16 + (bot - 1) * 100 / totallines; 246 | if(p2 > 116) { p2 = 116; } 247 | if(p1 < 16) { p1 = 16; } 248 | /* don't send ^S or ^Q because it will hang a layer using cu(1) */ 249 | if(p1 == ctrl('Q') || p1 == ctrl('S')) { ++p1; } 250 | if(p2 == ctrl('Q') || p2 == ctrl('S')) { ++p2; } 251 | } else { 252 | p1 = p2 = 16; 253 | } 254 | (void)printf("\033W%c%c", p1, p2); 255 | } 256 | } 257 | 258 | /* get the mouse information */ 259 | MOUSE *getmouseaction(char leading_char) { 260 | static MOUSE m; 261 | 262 | #if UNIXPC 263 | 264 | if(unixpcmouse == true && leading_char == ESC) { 265 | 266 | /* Called if cscope received an ESC character. See if it is 267 | * a mouse report and if so, decipher it. A mouse report 268 | * looks like: "[?xx;yy;b;rM" 269 | */ 270 | int x = 0, y = 0, button = 0, reason = 0; 271 | int i; 272 | 273 | /* Get a mouse report. The form is: XX;YY;B;RM where 274 | * XX is 1,2, or 3 decimal digits with the X pixel position. 275 | * Similarly for YY. B is a single decimal digit with the 276 | * button number (4 for one, 2 for two, and 1 for three). 277 | * R is the reason for the mouse report. 278 | * 279 | * In general, the input is read until the mouse report has 280 | * been completely read in or we have discovered that this 281 | * escape sequence is falseT a mouse report. In the latter case 282 | * return the last character read to the input stream with 283 | * myungetch(). 284 | */ 285 | 286 | /* Check for "[?" being next 2 chars */ 287 | if(((i = getch()) != '[') || ((i = getch()) != '?')) { 288 | myungetch(i); 289 | return (NULL); 290 | } 291 | 292 | /* Grab the X position (in pixels) */ 293 | while(isdigit(i = getch())) { 294 | x = (x * 10) + (i - '0'); 295 | } 296 | if(i != ';') { 297 | myungetch(i); 298 | return (NULL); /* not a mouse report after all */ 299 | } 300 | 301 | /* Grab the Y position (in pixels) */ 302 | while(isdigit(i = getch())) { 303 | y = (y * 10) + (i - '0'); 304 | } 305 | if(i != ';') { 306 | myungetch(i); 307 | return (NULL); 308 | } 309 | 310 | /* Get which button */ 311 | if((button = getch()) > '4') { 312 | myungetch(button); 313 | return (NULL); 314 | } 315 | if((i = getch()) != ';') { 316 | myungetch(i); 317 | return (NULL); 318 | } 319 | 320 | /* Get the reason for this mouse report */ 321 | if((reason = getch()) > '8') { 322 | myungetch(reason); 323 | return (NULL); 324 | } 325 | 326 | /* sequence should terminate with an 'M' */ 327 | if((i = getch()) != 'M') { 328 | myungetch(i); 329 | return (NULL); 330 | } 331 | 332 | 333 | /* OK. We get a mouse report whenever a button is depressed 334 | * or released. Let's ignore the report whenever the button 335 | * is depressed until when I am ready to implement sweeping. 336 | */ 337 | if(reason != '2') { return (NULL); /* '2' means button is released */ } 338 | 339 | /************************************************************ 340 | * Always indicate button 1 irregardless of which button was 341 | * really pushed. 342 | ************************************************************/ 343 | m.button = 1; 344 | 345 | /************************************************************ 346 | * Convert pixel coordinates to line and column coords. 347 | * The height and width are obtained using an ioctl() call 348 | * in mouseinit(). This assumes that variable width chars 349 | * are not being used ('though it would probably work anyway). 350 | ************************************************************/ 351 | 352 | m.x1 = x / uw_hs; /* pixel/horizontal_spacing */ 353 | m.y1 = y / uw_vs; /* pixel/vertical_spacing */ 354 | 355 | /* "null" out the other fields */ 356 | m.percent = m.x2 = m.y2 = -1; 357 | } else 358 | #endif /* not UNIXPC */ 359 | 360 | if(mouse == true && leading_char == ctrl('X')) { 361 | switch(getch()) { 362 | case ctrl('_'): /* click */ 363 | if((m.button = getch()) == '0') { /* if scrollbar */ 364 | m.percent = getpercent(); 365 | } else { 366 | m.x1 = getcoordinate(); 367 | m.y1 = getcoordinate(); 368 | m.x2 = m.y2 = -1; 369 | } 370 | break; 371 | 372 | case ctrl(']'): /* sweep */ 373 | m.button = getch(); 374 | m.x1 = getcoordinate(); 375 | m.y1 = getcoordinate(); 376 | m.x2 = getcoordinate(); 377 | m.y2 = getcoordinate(); 378 | break; 379 | default: 380 | return (NULL); 381 | } 382 | } else 383 | return (NULL); 384 | 385 | return (&m); 386 | } 387 | 388 | /* get a row or column coordinate from a mouse button click or sweep */ 389 | static int getcoordinate(void) { 390 | int c, next; 391 | 392 | c = getch(); 393 | next = 0; 394 | if(c == ctrl('A')) { 395 | next = 95; 396 | c = getch(); 397 | } 398 | if(c < ' ') { return (0); } 399 | return (next + c - ' '); 400 | } 401 | 402 | /* get a percentage */ 403 | static int getpercent(void) { 404 | int c = getch(); 405 | 406 | if(c < 16) { return 0; } 407 | if(c > 120) { return 100; } 408 | 409 | return (c - 16); 410 | } 411 | 412 | int process_mouse() { 413 | int i; 414 | MOUSE *p; 415 | if((p = getmouseaction(DUMMYCHAR)) == NULL) { 416 | return false; /* unknown control sequence */ 417 | } 418 | /* if the button number is a scrollbar tag */ 419 | if(p->button == '0') { 420 | // scrollbar(p); // XXX 421 | return false; 422 | } 423 | /* ignore a sweep */ 424 | if(p->x2 >= 0) { return false; } 425 | /* if this is a line selection */ 426 | if(p->y1 > FLDLINE) { 427 | 428 | /* find the selected line */ 429 | /* note: the selection is forced into range */ 430 | for(i = disprefs - 1; i > 0; --i) { 431 | if(p->y1 >= 1/*displine[i]*/) { return false; } 432 | } 433 | /* display it in the file with the editor */ 434 | editref(i); 435 | } else { /* this is an input field selection */ 436 | field = p->y1 - FLDLINE; 437 | /* force it into range */ 438 | if(field >= FIELDS) { field = FIELDS - 1; } 439 | return false; 440 | } 441 | 442 | return false; 443 | } 444 | 445 | // NOTE: this comes from command.c 446 | // /* scrollbar actions */ 447 | // static void scrollbar(MOUSE *p) { 448 | // // XXX 449 | // ///* reposition list if it makes sense */ 450 | // // if (totallines == 0) { 451 | // // return; 452 | // // } 453 | // // switch (p->percent) { 454 | // 455 | // // case 101: /* scroll down one page */ 456 | // // if (nextline + mdisprefs > totallines) { 457 | // // nextline = totallines - mdisprefs + 1; 458 | // // } 459 | // // break; 460 | // 461 | // // case 102: /* scroll up one page */ 462 | // // nextline = topline - mdisprefs; 463 | // // if (nextline < 1) { 464 | // // nextline = 1; 465 | // // } 466 | // // break; 467 | // 468 | // // case 103: /* scroll down one line */ 469 | // // nextline = topline + 1; 470 | // // break; 471 | // 472 | // // case 104: /* scroll up one line */ 473 | // // if (topline > 1) { 474 | // // nextline = topline - 1; 475 | // // } 476 | // // break; 477 | // // default: 478 | // // nextline = p->percent * totallines / 100; 479 | // // } 480 | // ////seekline(nextline); 481 | // } 482 | -------------------------------------------------------------------------------- /source/mypopen.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "global.h" /* pid_t, shell, and basename() */ 39 | 40 | #define tst(a, b) (*mode == 'r' ? (b) : (a)) 41 | #define RDR 0 42 | #define WTR 1 43 | 44 | #ifdef FD_CLOEXEC 45 | # define CLOSE_ON_EXEC FD_CLOEXEC 46 | #else 47 | # define CLOSE_ON_EXEC 1 48 | #endif 49 | 50 | #ifdef HAVE_IO_H 51 | # include /* for setmode() */ 52 | #endif 53 | 54 | static pid_t popen_pid[20]; 55 | static void (*tstat)(int); 56 | 57 | int myopen(const char * path, int flag, int mode) { 58 | /* opens a file descriptor and then sets close-on-exec for the file */ 59 | int fd; 60 | 61 | /* If file is not explicitly in Binary mode, make 62 | * sure we override silly Cygwin behaviour of automatic binary 63 | * mode for files in "binary mounted" paths */ 64 | #if O_BINARY != O_TEXT 65 | if(!(flag | O_BINARY)) flag |= O_TEXT; 66 | #endif 67 | if(mode) 68 | fd = open(path, flag, mode); 69 | else 70 | fd = open(path, flag); 71 | 72 | if(fd != -1 && (fcntl(fd, F_SETFD, CLOSE_ON_EXEC) != -1)) 73 | return (fd); 74 | 75 | else { 76 | /* Ensure that if the fcntl fails and fd is valid, then 77 | the file is closed properly. In general this should 78 | not happen. */ 79 | if(fd != -1) { close(fd); } 80 | 81 | return (-1); 82 | } 83 | } 84 | 85 | FILE *myfopen(const char * path, const char * mode) { 86 | /* opens a file pointer and then sets close-on-exec for the file */ 87 | FILE *fp; 88 | 89 | fp = fopen(path, mode); 90 | 91 | #ifdef SETMODE 92 | if(fp && !strchr(mode, 'b')) { SETMODE(fileno(fp), O_TEXT); } 93 | #endif /* SETMODE */ 94 | 95 | if(fp && (fcntl(fileno(fp), F_SETFD, CLOSE_ON_EXEC) != -1)) { 96 | return (fp); 97 | } 98 | 99 | if(fp) { 100 | fclose(fp); 101 | } 102 | return (NULL); 103 | } 104 | 105 | /* XXX: these functions should go as soon as build.c is sorted out 106 | */ 107 | FILE *mypopen(char *cmd, char *mode) { 108 | int p[2]; 109 | pid_t *poptr; 110 | int myside, yourside; 111 | pid_t pid; 112 | 113 | if(pipe(p) < 0) return (NULL); 114 | myside = tst(p[WTR], p[RDR]); 115 | yourside = tst(p[RDR], p[WTR]); 116 | if((pid = fork()) == 0) { 117 | /* myside and yourside reverse roles in child */ 118 | int stdio; 119 | 120 | /* close all pipes from other popen's */ 121 | for(poptr = popen_pid; poptr < popen_pid + 20; poptr++) { 122 | if(*poptr) (void)close(poptr - popen_pid); 123 | } 124 | stdio = tst(0, 1); 125 | close(myside); 126 | close(stdio); 127 | fcntl(yourside, F_DUPFD, stdio); 128 | close(yourside); 129 | execlp(shell, basename(shell), "-c", cmd, (void *)0); 130 | _exit(1); 131 | } else if(pid > 0) { 132 | tstat = signal(SIGTSTP, SIG_DFL); 133 | } 134 | if(pid == -1) { 135 | return (NULL); 136 | } 137 | popen_pid[myside] = pid; 138 | (void)close(yourside); 139 | return (fdopen(myside, mode)); 140 | } 141 | 142 | int mypclose(FILE *ptr) { 143 | int f; 144 | pid_t r; 145 | int status = -1; 146 | sighandler_t hstat, istat, qstat; 147 | 148 | f = fileno(ptr); 149 | UNUSED(fclose(ptr)); 150 | istat = signal(SIGINT, SIG_IGN); 151 | qstat = signal(SIGQUIT, SIG_IGN); 152 | hstat = signal(SIGHUP, SIG_IGN); 153 | while((r = wait(&status)) != popen_pid[f] && r != -1) { ; } 154 | if(r == -1) status = -1; 155 | UNUSED(signal(SIGINT, istat)); 156 | UNUSED(signal(SIGQUIT, qstat)); 157 | UNUSED(signal(SIGHUP, hstat)); 158 | UNUSED(signal(SIGTSTP, tstat)); 159 | /* mark this pipe closed */ 160 | popen_pid[f] = 0; 161 | return (status); 162 | } 163 | -------------------------------------------------------------------------------- /source/opt.c: -------------------------------------------------------------------------------- 1 | #include "global.h" 2 | 3 | #include "build.h" 4 | #include "vpath.h" 5 | #include "version.inc" 6 | #include "auto_vararg.h" 7 | #include "help.h" 8 | 9 | #include /* atoi */ 10 | #include 11 | 12 | /* defaults for unset environment variables */ 13 | #define DEFAULT_EDITOR "vi" 14 | #define DEFAULT_HOME "/" /* no $HOME --> use root directory */ 15 | #define DEFAULT_SHELL "sh" 16 | #define DEFAULT_LINEFLAG "+%s" /* default: used by vi and emacs */ 17 | #define DEFAULT_TMPDIR "/tmp" 18 | 19 | /* environment variable holders */ 20 | char * editor; 21 | char * home; 22 | char * shell; 23 | char * lineflag; 24 | char * tmpdir; 25 | bool lineflagafterfile; 26 | /* XXX: this might be a war crime; 27 | * its currently required for respecting kernel mode 28 | */ 29 | const char * incdir = NULL; 30 | 31 | /* option holders */ 32 | bool remove_symfile_onexit = false; 33 | bool onesearch; /* one search only in line mode */ 34 | char *reflines; /* symbol reference lines file */ 35 | bool invertedindex; /* the database has an inverted index */ 36 | bool preserve_database = false; /* consider the crossref up-to-date */ 37 | bool kernelmode; /* don't use DEFAULT_INCLUDE_DIRECTORY - bad for kernels */ 38 | bool linemode = false; /* use line oriented user interface */ 39 | bool verbosemode = false; /* print extra information on line mode */ 40 | bool recurse_dir = false; /* recurse dirs when searching for src files */ 41 | char *namefile; /* file of file names */ 42 | 43 | /* From a list of envirnment variable names, 44 | * return the first valid variable value 45 | * or the user given default. 46 | */ 47 | #define coalesce_env(def, ...) _coalesce_env(def, PP_NARG(__VA_ARGS__), __VA_ARGS__) 48 | static inline 49 | char * _coalesce_env(char * mydefault, size_t argc, ...) { 50 | char * r = mydefault; 51 | va_list va; 52 | va_start(va, argc); 53 | 54 | for (int i = 0; i < argc; i++) { 55 | char * value = va_arg(va, char*); 56 | value = getenv(value); 57 | 58 | if (value != NULL 59 | && *value != '\0') { 60 | r = value; 61 | goto end; 62 | } 63 | } 64 | 65 | end: 66 | va_end(va); 67 | return r; 68 | } 69 | 70 | /* XXX: Add CSOPE_* equivalents while preserving the originals. 71 | * DO NOT do it without writting documentation 72 | */ 73 | void readenv(bool preserve_database) { 74 | editor = coalesce_env(DEFAULT_EDITOR, "CSCOPE_EDITOR", "VIEWER", "EDITOR"); 75 | home = coalesce_env(DEFAULT_HOME, "HOME"); 76 | shell = coalesce_env(DEFAULT_SHELL, "SHELL"); 77 | lineflag = coalesce_env(DEFAULT_LINEFLAG, "CSCOPE_LINEFLAG"); 78 | tmpdir = coalesce_env(DEFAULT_TMPDIR, "TMPDIR"); 79 | 80 | lineflagafterfile = getenv("CSCOPE_LINEFLAG_AFTER_FILE") ? 1 : 0; 81 | 82 | if (!preserve_database) { 83 | incdir = coalesce_env(DEFAULT_INCLUDE_DIRECTORY, "INCDIR"); 84 | /* get source directories from the environment */ 85 | const char * const my_source_dirs = getenv("SOURCEDIRS"); 86 | if(my_source_dirs) { sourcedir(my_source_dirs); } 87 | /* get include directories from the environment */ 88 | const char * const my_include_dirs = getenv("INCLUDEDIRS"); 89 | if(my_include_dirs) { includedir(my_source_dirs); } 90 | } 91 | } 92 | 93 | char * * parse_options(const int argc, const char * const * const argv) { 94 | int opt; 95 | int longind; 96 | char path[PATHLEN + 1]; /* file path */ 97 | char *s; 98 | 99 | struct option lopts[] = { 100 | {"help", 0, NULL, 'h'}, 101 | {"version", 0, NULL, 'V'}, 102 | {0, 0, 0, 0 }, 103 | }; 104 | 105 | while((opt = getopt_long(argc, (char**)argv, 106 | "hVbcCdeF:f:I:i:kLl0:1:2:3:4:5:6:7:8:9:P:p:qRs:TUuvX", 107 | lopts, 108 | &longind)) != -1) { 109 | switch(opt) { 110 | case '?': 111 | usage(); 112 | myexit(1); 113 | break; 114 | case 'h': 115 | longusage(); 116 | myexit(1); 117 | break; 118 | case 'V': 119 | fprintf(stderr, PROGRAM_NAME ": version %d%s\n", FILEVERSION, FIXVERSION); 120 | myexit(0); 121 | break; 122 | case 'X': 123 | remove_symfile_onexit = true; 124 | break; 125 | case ASCII_DIGIT: 126 | /* The input fields numbers for line mode operation */ 127 | field = opt - '0'; 128 | if(strlen(optarg) > PATHLEN) { 129 | postfatal("\ 130 | cscope: pattern too long, cannot be > \ 131 | %d characters\n", 132 | PATLEN); 133 | } 134 | strcpy(input_line, optarg); 135 | break; 136 | case 'b': /* only build the cross-reference */ 137 | buildonly = true; 138 | linemode = true; 139 | break; 140 | case 'c': /* ASCII characters only in crossref */ 141 | compress = false; 142 | break; 143 | case 'C': /* turn on caseless mode for symbol searches */ 144 | caseless = true; 145 | egrepcaseless(caseless); /* simulate egrep -i flag */ 146 | break; 147 | case 'd': /* consider crossref up-to-date */ 148 | preserve_database = true; 149 | break; 150 | case 'e': /* suppress ^E prompt between files */ 151 | editallprompt = false; 152 | break; 153 | case 'k': /* ignore DEFAULT_INCLUDE_DIRECTORY */ 154 | kernelmode = true; 155 | break; 156 | case 'L': 157 | onesearch = true; 158 | /* FALLTHROUGH */ 159 | case 'l': 160 | linemode = true; 161 | break; 162 | case 'v': 163 | verbosemode = true; 164 | break; 165 | case 'q': /* quick search */ 166 | invertedindex = true; 167 | break; 168 | case 'T': /* truncate symbols to 8 characters */ 169 | trun_syms = true; 170 | break; 171 | case 'u': /* unconditionally build the cross-reference */ 172 | unconditional = true; 173 | break; 174 | case 'U': /* assume some files have changed */ 175 | fileschanged = true; 176 | break; 177 | case 'R': 178 | recurse_dir = true; 179 | break; 180 | case 'f': /* alternate cross-reference file */ 181 | reffile = optarg; 182 | if(strlen(reffile) > sizeof(path) - 3) { 183 | postfatal("\ 184 | cscope: reffile too long, cannot \ 185 | be > %d characters\n", 186 | sizeof(path) - 3); 187 | /* NOTREACHED */ 188 | } 189 | strcpy(path, reffile); 190 | 191 | s = path + strlen(path); 192 | strcpy(s, ".in"); 193 | /*coverity[overwrite_var]*/ 194 | invname = strdup(path); 195 | strcpy(s, ".po"); 196 | /*coverity[overwrite_var]*/ 197 | invpost = strdup(path); 198 | break; 199 | 200 | case 'F': /* symbol reference lines file */ 201 | reflines = optarg; 202 | break; 203 | case 'i': /* file containing file names */ 204 | namefile = optarg; 205 | break; 206 | case 'I': /* #include file directory */ 207 | includedir(optarg); 208 | break; 209 | case 'p': /* file path components to display */ 210 | dispcomponents = atoi(optarg); 211 | break; 212 | case 'P': /* prepend path to file names */ 213 | prependpath = optarg; 214 | break; 215 | case 's': /* additional source file directory */ 216 | sourcedir(optarg); 217 | break; 218 | } 219 | } 220 | 221 | // Sanity checks 222 | /* XXX remove if/when clearerr() in dir.c does the right thing. */ 223 | if(namefile && strcmp(namefile, "-") == 0 && !buildonly) { 224 | postfatal(PROGRAM_NAME ": Must use -b if file list comes from stdin\n"); 225 | /* NOTREACHED */ 226 | } 227 | 228 | /* NOTE: 229 | * we return where option arguments stop, 230 | * assuming that heres a list of files after them, 231 | * we process these later 232 | */ 233 | return (char**)(argv + optind); 234 | } 235 | -------------------------------------------------------------------------------- /source/path.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* get a file's base name from its path name */ 34 | 35 | #include "global.h" 36 | 37 | #include 38 | #include 39 | 40 | const char *basename(const char *path) { 41 | const char *s; 42 | 43 | if((s = strrchr(path, '/')) != 0) { return (s + 1); } 44 | return path; 45 | } 46 | 47 | /* get the requested path components */ 48 | char *pathcomponents(char *path, int components) { 49 | char * s = path + strlen(path) - 1; 50 | for(int i = 0; i < components; i++) { 51 | while(s > path && *--s != '/') { 52 | ; 53 | } 54 | } 55 | if(s > path && *s == '/') { ++s; } 56 | return (s); 57 | } 58 | 59 | /* Remove multiple slashes from a path string. */ 60 | static inline 61 | void path_remove_multiple_slashes(char *path) { 62 | char *read = path; 63 | char *write = path; 64 | 65 | while (*read) { 66 | *write++ = *read++; 67 | if (*(write - 1) == '/') { 68 | while (*read == '/') { 69 | read++; 70 | } 71 | } 72 | } 73 | *write = '\0'; 74 | } 75 | 76 | 77 | static inline 78 | void path_remove_current_directory_references(char *path) { 79 | char *read = path; 80 | char *write = path; 81 | 82 | while (*read) { 83 | if (read[0] == '.' && read[1] == '/' && 84 | (read == path || *(read - 1) == '/')) { 85 | read += 2; // Skip "./" 86 | } else { 87 | *write++ = *read++; 88 | } 89 | } 90 | *write = '\0'; 91 | } 92 | 93 | 94 | static inline 95 | void path_remove_parent_directory_references(char *path) { 96 | char *read = path; 97 | char *write = path; 98 | 99 | while (*read) { 100 | if (read[0] == '/' && read[1] == '.' && read[2] == '.' && 101 | (read[3] == '/' || read[3] == '\0')) { 102 | read += (read[3] == '/') ? 4 : 3; // Skip "/.." 103 | if (write > path) { 104 | write--; // Go back to previous slash 105 | while (write > path && *(write - 1) != '/') { 106 | write--; 107 | } 108 | } 109 | } else { 110 | *write++ = *read++; 111 | } 112 | } 113 | *write = '\0'; 114 | } 115 | 116 | 117 | /* 118 | * compress_path(pathname) 119 | * 120 | * This compresses pathnames. All strings of multiple slashes are 121 | * changed to a single slash. All occurrences of "./" are removed. 122 | * Whenever possible, strings of "/.." are removed together with 123 | * the directory names that they follow. 124 | * 125 | * WARNING: since pathname is altered by this function, it should 126 | * be located in a temporary buffer. This avoids the problem 127 | * of accidently changing strings obtained from makefiles 128 | * and stored in global structures. 129 | */ 130 | char *compress_path(const char *pathname_) { 131 | if (pathname_ == NULL) { 132 | return NULL; 133 | } 134 | 135 | char *pathname = strdup(pathname_); 136 | 137 | /* 138 | * do not change the path if it has no "/" 139 | */ 140 | if(strchr(pathname, '/') == NULL) { 141 | return (pathname); 142 | } 143 | 144 | /* Step 1: Remove multiple slashes */ 145 | path_remove_multiple_slashes(pathname); 146 | 147 | /* Step 2: Remove curr dir "./" references */ 148 | path_remove_current_directory_references(pathname); 149 | 150 | /* Step 3: Remove parent dir "/.." references */ 151 | path_remove_parent_directory_references(pathname); 152 | 153 | /* Handle trailing slashes */ 154 | size_t len = strlen(pathname); 155 | if (len > 1 && pathname[len - 1] == '/') { 156 | pathname[len - 1] = '\0'; 157 | } 158 | 159 | /* Step 5: If the path is empty, return "." */ 160 | if (*pathname == '\0') { 161 | strcpy(pathname, "."); 162 | } 163 | 164 | return pathname; 165 | } 166 | 167 | static 168 | char *nextfield(char *p) { 169 | while(*p && *p != ':') { ++p; } 170 | if(*p) { *p++ = 0; } 171 | return p; 172 | } 173 | 174 | /* 175 | * logdir() 176 | * 177 | * This routine does not use the getpwent(3) library routine 178 | * because the latter uses the stdio package. The allocation of 179 | * storage in this package destroys the integrity of the shell's 180 | * storage allocation. 181 | */ 182 | char *logdir(char *name) { 183 | #define BUFFER_SIZE 160 184 | static char line[BUFFER_SIZE]; 185 | char *p; 186 | int i, j; 187 | int pwf; 188 | 189 | /* attempt to open the password file */ 190 | if((pwf = myopen("/etc/passwd", 0, 0)) == -1) return (0); 191 | 192 | /* find the matching password entry */ 193 | do { 194 | /* get the next line in the password file */ 195 | i = read(pwf, line, BUFFER_SIZE-1); 196 | for(j = 0; j < i; j++) { 197 | if(line[j] == '\n') { break; } 198 | } 199 | /* return a null pointer if the whole file has been read */ 200 | if(j >= i) return (0); 201 | line[++j] = 0; /* terminate the line */ 202 | (void)lseek(pwf, (long)(j - i), 1); /* point at the next line */ 203 | p = nextfield(line); /* get the logname */ 204 | } while(*name != *line || /* fast pretest */ 205 | strcmp(name, line) != 0); 206 | (void)close(pwf); 207 | 208 | /* skip the intervening fields */ 209 | p = nextfield(p); 210 | p = nextfield(p); 211 | p = nextfield(p); 212 | p = nextfield(p); 213 | 214 | /* return the login directory */ 215 | (void)nextfield(p); 216 | return p; 217 | } 218 | -------------------------------------------------------------------------------- /source/readline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "global.h" 5 | #include "build.h" 6 | #include 7 | 8 | static int input_available = 0; 9 | static int input_char; 10 | char input_line[PATLEN + 1]; 11 | 12 | /* used for saving a line not [Enter]-ed yet, 13 | * so its not lost if the user scrolls the history 14 | */ 15 | static struct PARTIAL_LINE { 16 | bool is_active; 17 | char* line; 18 | int pos; 19 | } partial_line = { 20 | .line = NULL, 21 | .is_active = true 22 | }; 23 | 24 | 25 | static inline void previous_history_proxy(void); 26 | static inline void next_history_proxy(void); 27 | 28 | 29 | bool interpret(int c) { 30 | /* A switch is faster then binding Readline to a billion functions 31 | * and since KEY_* values can't be bound anyways (values too large 32 | * (because while the first argument of rl_bind_key() is an int, 33 | * only unsigned chars are valid)), handling everything here 34 | * creates consistency too. 35 | */ 36 | switch(c){ 37 | case KEY_BACKSPACE: 38 | rl_rubout(1, 0); 39 | break; 40 | case KEY_UP: 41 | previous_history_proxy(); 42 | break; 43 | case KEY_DOWN: 44 | next_history_proxy(); 45 | break; 46 | case KEY_LEFT: 47 | if(rl_point) { 48 | --rl_point; 49 | } 50 | break; 51 | case KEY_RIGHT: 52 | if(rl_point < rl_end) { 53 | ++rl_point; 54 | } 55 | break; 56 | case ESC: 57 | case ctrl('X'): 58 | process_mouse(); 59 | break; 60 | default: 61 | input_char = c; 62 | input_available = 1; 63 | rl_callback_read_char(); 64 | return 0; 65 | } 66 | //XXX: 67 | // rl_bind_key(ctrl('\\'), /**/); /* bypass bindings */ 68 | 69 | window_change |= CH_INPUT; 70 | return 0; 71 | } 72 | 73 | static int getc_function(FILE *ignore) { 74 | UNUSED(ignore); 75 | 76 | input_available = 0; 77 | return input_char; 78 | } 79 | 80 | static int input_available_hook() { 81 | return input_available; 82 | } 83 | 84 | static void redisplay_function() { 85 | window_change |= CH_INPUT; 86 | } 87 | 88 | static void callback_handler(char *line) { 89 | if(!line) { 90 | input_mode = INPUT_NORMAL; 91 | return; 92 | } 93 | 94 | add_history(line); 95 | 96 | switch(input_mode) { 97 | case INPUT_NORMAL: { 98 | strncpy(input_line, line, PATLEN); 99 | search(input_line); 100 | horswp_window(); 101 | curdispline = 0; 102 | current_page = 0; 103 | PCS_reset(); 104 | } break; 105 | case INPUT_CHANGE_TO: { 106 | strncpy(newpat, line, PATLEN); 107 | change = (bool *)calloc(totallines, sizeof(*change)); 108 | input_mode = INPUT_CHANGE; 109 | force_window(); 110 | } return; 111 | case INPUT_APPEND: { 112 | char filename[PATHLEN + 1]; 113 | FILE* file; 114 | char ch; 115 | shellpath(filename, sizeof(filename), line); 116 | file = fopen(filename, "a+"); 117 | if (file) { 118 | seekpage(0); 119 | while ((ch = getc(refsfound)) != EOF) { 120 | putc(ch, file); 121 | } 122 | fclose(file); 123 | } else { 124 | postmsg2("Failed to open file."); 125 | } 126 | input_mode = INPUT_NORMAL; 127 | } return; 128 | case INPUT_READ: { 129 | char filename[PATHLEN + 1]; 130 | shellpath(filename, sizeof(filename), line); 131 | if (!readrefs(filename)) { 132 | postmsg2("Ignoring an empty file"); 133 | } 134 | window_change |= CH_INPUT | CH_RESULT; 135 | input_mode = INPUT_NORMAL; 136 | } return; 137 | } 138 | 139 | switch(field) { 140 | case CHANGE: 141 | if(totallines == 0){ return; } 142 | input_mode = INPUT_CHANGE_TO; 143 | force_window(); 144 | break; 145 | case DEFINITION: 146 | case FILENAME: 147 | if(totallines == 1) { editref(0); } 148 | break; 149 | } 150 | } 151 | 152 | static inline void previous_history_proxy(){ 153 | HIST_ENTRY* i = previous_history(); 154 | if(!i) { return; } 155 | 156 | if(partial_line.is_active){ 157 | free(partial_line.line); 158 | partial_line = (struct PARTIAL_LINE){ 159 | .line = strdup(rl_line_buffer), 160 | .pos = rl_point, 161 | .is_active = false 162 | }; 163 | } 164 | // 165 | rl_replace_line(i->line, 0); 166 | rl_point = strlen(i->line); 167 | } 168 | 169 | static inline void next_history_proxy(){ 170 | HIST_ENTRY* i = next_history(); 171 | if(i){ 172 | rl_replace_line(i->line, 0); 173 | rl_point = strlen(i->line); 174 | }else if(!partial_line.is_active){ 175 | rl_replace_line(partial_line.line, 0); 176 | rl_point = partial_line.pos; 177 | partial_line.is_active = true; 178 | } 179 | } 180 | 181 | void rlinit() { 182 | rl_readline_name = PROGRAM_NAME; 183 | 184 | using_history(); 185 | 186 | rl_catch_signals = 0; 187 | rl_catch_sigwinch = 0; 188 | rl_prep_term_function = NULL; 189 | rl_deprep_term_function = NULL; 190 | rl_change_environment = 0; 191 | 192 | rl_getc_function = getc_function; 193 | rl_input_available_hook = input_available_hook; 194 | rl_redisplay_function = redisplay_function; 195 | rl_callback_handler_install("", callback_handler); 196 | } 197 | -------------------------------------------------------------------------------- /source/refsfound.c: -------------------------------------------------------------------------------- 1 | #include "global.h" 2 | /* Possibly rename */ 3 | 4 | struct FILE; 5 | 6 | /* Page cursor stack */ 7 | static FILE **hto_page = &refsfound; 8 | #define PCS_MAXPAGE 16 9 | static size_t PCS_pos[PCS_MAXPAGE] = {0}; 10 | static size_t PCS_top = 0; 11 | 12 | long seekpage(const size_t i) { 13 | if(i > PCS_MAXPAGE - 1) { return -1; } 14 | 15 | if(i < PCS_top) { 16 | fseek(*hto_page, PCS_pos[i], SEEK_SET); 17 | return PCS_pos[i]; 18 | } 19 | 20 | fseek(*hto_page, PCS_pos[PCS_top], SEEK_SET); 21 | 22 | size_t lc = 0; 23 | while(PCS_top < i) { 24 | const char c = getc(*hto_page); 25 | if(c == '\n') { ++lc; } 26 | if(c == EOF) { return -1; } 27 | if(lc == mdisprefs) { PCS_pos[++PCS_top] = ftell(*hto_page); } 28 | } 29 | return PCS_pos[PCS_top]; 30 | } 31 | 32 | long seekrelline(unsigned i) { 33 | seekpage(current_page); 34 | size_t lc = 0; 35 | while(lc < i) { 36 | const char c = getc(*hto_page); 37 | assert("seekrelline() tried to read past the reference file" && !(c == EOF)); 38 | if(c == '\n') { ++lc; } 39 | } 40 | return ftell(*hto_page); 41 | } 42 | 43 | void PCS_reset(void) { 44 | PCS_top = 0; 45 | } 46 | -------------------------------------------------------------------------------- /source/scanner.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 2001, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | #ifndef CSCOPE_SCANNER_H 34 | #define CSCOPE_SCANNER_H 35 | 36 | #include 37 | 38 | #undef YYLMAX 39 | #define YYLMAX STMTMAX + PATLEN + 1 /* scanner line buffer size */ 40 | 41 | /* cross-reference database mark characters (when new ones are added, 42 | * update the cscope.out format description in cscope.1) 43 | */ 44 | #define CLASSDEF 'c' 45 | #define DEFINE '#' 46 | #define DEFINEEND ')' 47 | #define ENUMDEF 'e' 48 | #define FCNCALL '`' 49 | #define FCNDEF '$' 50 | #define FCNEND '}' 51 | #define GLOBALDEF 'g' 52 | #define INCLUDE '~' 53 | #define MEMBERDEF 'm' 54 | #define NEWFILE '@' 55 | #define STRUCTDEF 's' 56 | #define TYPEDEF 't' 57 | #define UNIONDEF 'u' 58 | 59 | /* other scanner token types */ 60 | #define LEXEOF 0 61 | #define LEXERR 1 62 | #define IDENT 2 63 | #define NEWLINE 3 64 | 65 | /* scanner.l global data */ 66 | extern int first; /* buffer index for first char of symbol */ 67 | extern int last; /* buffer index for last char of symbol */ 68 | extern int lineno; /* symbol line number */ 69 | extern FILE *yyin; /* input file descriptor */ 70 | extern FILE *yyout; /* output file */ 71 | extern int myylineno; /* input line number */ 72 | 73 | extern char *my_yytext; /* private copy of input line */ 74 | extern size_t my_yyleng; /* ... and current length of it */ 75 | 76 | /* The master function exported by scanner.l */ 77 | int yylex(void); 78 | void initscanner(char *srcfile); 79 | 80 | #endif /* CSCOPE_SCANNER_H ends */ 81 | -------------------------------------------------------------------------------- /source/version.inc: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* cscope - interactive C symbol cross-reference 34 | * 35 | * Changing the cross-reference file part of the program version 36 | * forces rebuilding of the cross-reference. 37 | */ 38 | 39 | #ifndef CSCOPE_VERSION_H 40 | #define CSCOPE_VERSION_H 41 | 42 | #define FILEVERSION 16 /* Initial Open Source and Linux Port */ 43 | #define FIXVERSION ".0" /* feature and bug fix version */ 44 | 45 | #endif /* CSCOPE_VERSION_H */ 46 | -------------------------------------------------------------------------------- /source/vpath.c: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* vpinit - initialize vpdirs or update vpdirs based on currentdir */ 34 | 35 | #include /* stderr */ 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "vpath.h" 41 | 42 | #include "library.h" 43 | #include "global.h" 44 | #include "constants.h" 45 | 46 | char **vpdirs; /* directories (including current) in view path */ 47 | int vpndirs; /* number of directories in view path */ 48 | 49 | static inline int vp_element_count(const char * vpath); 50 | 51 | int vpaccess(const char * path, const mode_t amode) { 52 | char buf[MAXPATH + 1]; 53 | int r = access(path, amode); 54 | 55 | if (r != -1 56 | || path[0] == '/') { 57 | return r; 58 | } 59 | 60 | vpinit(NULL); 61 | for(int i = 1; i < vpndirs; i++) { 62 | (void)snprintf(buf, sizeof(buf), "%s/%s", vpdirs[i], path); 63 | r = access(buf, amode); 64 | if(r != -1) { break; } 65 | } 66 | 67 | return r; 68 | } 69 | 70 | /* XXX 71 | * const arg 72 | * scope i 73 | * scope s 74 | * do not dare to get current directory here 75 | * have vpath on the stack 76 | */ 77 | void vpinit(char *current_dir) { 78 | char *suffix; /* path from view path node */ 79 | char *vpath; /* VPATH environment variable value */ 80 | char buf[MAXPATH + 1]; 81 | int i; 82 | 83 | /* if an existing directory list is to be updated, free it */ 84 | if(current_dir != NULL && vpndirs > 0) { 85 | for(i = 0; i < vpndirs; ++i) { 86 | free(vpdirs[i]); 87 | } 88 | free(vpdirs); 89 | vpndirs = 0; 90 | } 91 | 92 | /* return if the directory list has been computed */ 93 | /* or there isn't a view path environment variable */ 94 | if(vpndirs > 0 || (vpath = getenv("VPATH")) == NULL || *vpath == '\0') { return; } 95 | /* if not given, get the current directory name */ 96 | if(current_dir == NULL && (current_dir = getcwd(buf, MAXPATH)) == NULL) { 97 | fprintf(stderr, PROGRAM_NAME ": cannot get current directory name\n"); 98 | return; 99 | } 100 | /* see if this directory is in the first view path node */ 101 | for(i = 0; vpath[i] == current_dir[i] && vpath[i] != '\0'; ++i) { 102 | ; 103 | } 104 | if((vpath[i] != ':' && vpath[i] != '\0') 105 | || (current_dir[i] != '/' && current_dir[i] != '\0')) { 106 | return; 107 | } 108 | suffix = ¤t_dir[i]; 109 | 110 | /* count the nodes in the view path */ 111 | vpndirs = vp_element_count(vpath); 112 | 113 | /* create the source directory list */ 114 | vpdirs = malloc(vpndirs * sizeof(*vpdirs)); 115 | 116 | /* don't change VPATH in the environment */ 117 | vpath = strdup(vpath); 118 | 119 | char * s = vpath; 120 | /* split the view path into nodes */ 121 | for(int i = 0; *s != '\0'; ++i) { 122 | vpdirs[i] = s; 123 | while(*s != '\0' && *++s != ':') { 124 | if(*s == '\n') { *s = '\0'; } 125 | } 126 | if(*s != '\0') { *s++ = '\0'; } 127 | } 128 | /* convert the view path nodes to directories */ 129 | for(int i = 0; i < vpndirs; ++i) { 130 | s = malloc(strlen(vpdirs[i]) + strlen(suffix) + 1); 131 | (void)strcpy(s, vpdirs[i]); 132 | (void)strcat(s, suffix); 133 | vpdirs[i] = s; 134 | } 135 | free(vpath); 136 | } 137 | 138 | #define OPENFLAG_READ 0 139 | int vpopen(const char * path, const int oflag) { 140 | char buf[MAXPATH + 1]; 141 | int r = myopen(path, oflag, 0666); 142 | 143 | if (r != -1 144 | || path[0] == '/' 145 | || oflag != OPENFLAG_READ) { 146 | return r; 147 | } 148 | 149 | vpinit(NULL); 150 | for(int i = 1; i < vpndirs; i++) { 151 | (void)snprintf(buf, sizeof(buf), "%s/%s", vpdirs[i], path); 152 | r = myopen(buf, oflag, 0666); 153 | if(r != -1) { break; } 154 | } 155 | 156 | return (r); 157 | } 158 | 159 | FILE * vpfopen(const char *filename, const char * type) { 160 | char buf[MAXPATH + 1]; 161 | FILE * r = myfopen(filename, type); 162 | 163 | if (r != NULL 164 | || filename[0] == '/' 165 | || type[0] != 'r') { /* && strcmp(type, "r") == 0 */ /* HBB: this breaks if type=="rb" */ 166 | return r; 167 | } 168 | 169 | vpinit(NULL); 170 | for(int i = 1; i < vpndirs; i++) { 171 | (void)snprintf(buf, sizeof(buf), "%s/%s", vpdirs[i], filename); 172 | r = myfopen(buf, type); 173 | if(r != NULL) { break; } 174 | } 175 | 176 | return r; 177 | } 178 | 179 | /* NOTE: 180 | * the original code tested for a trailing ':', 181 | * however, thats equivalent to having and empty path 182 | * which could arise from "::" 183 | */ 184 | static inline 185 | int vp_element_count(const char * vpath) { 186 | int r = strspn(vpath, ":"); 187 | ++r; 188 | return r; 189 | } 190 | -------------------------------------------------------------------------------- /source/vpath.h: -------------------------------------------------------------------------------- 1 | /*=========================================================================== 2 | Copyright (c) 1998-2000, The Santa Cruz Operation 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | *Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | 11 | *Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | *Neither name of The Santa Cruz Operation nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 20 | IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT falseT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 23 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT falseT LIMITED TO, PROCUREMENT OF 25 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 | DAMAGE. 31 | =========================================================================*/ 32 | 33 | /* 34 | * VPATH assumptions: 35 | * VPATH is the environment variable containing the view path 36 | * where each path name is followed by ':', '\n', or '\0'. 37 | * Embedded blanks are considered part of the path. 38 | */ 39 | 40 | #ifndef CSCOPE_VP_H 41 | #define CSCOPE_VP_H 42 | 43 | #define MAXPATH 200 /* max length for entire name */ 44 | 45 | #ifdef HAVE_CONFIG_H 46 | # include "config.h" 47 | #else 48 | # define HAVE_FCNTL_H 1 /* in case of doubt, assume it's there */ 49 | #endif 50 | #ifdef HAVE_FCNTL_H 51 | # include /* needed for O_... open flags */ 52 | #endif 53 | 54 | #include 55 | #include 56 | 57 | extern char **vpdirs; /* directories (including current) in view path */ 58 | extern int vpndirs; /* number of directories in view path */ 59 | 60 | void vpinit(char *current_dir); 61 | int vpopen(const char * path, const int oflag); 62 | int vpaccess(const char * path, const mode_t amode); 63 | FILE * vpfopen(const char * filename, const char * type); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /test/CMDTEST_main.rb: -------------------------------------------------------------------------------- 1 | # NOTE: Kernel mode should be used accross the board, 2 | # because system headers are volatile. 3 | # Writting tests for them would be foolish. 4 | # They could even introduce interfering 5 | # symbols in the future by pure chance, 6 | # if not completely ignored. 7 | 8 | # The following variables are magick numbers based on `dummy_project/`. 9 | $f_definition_line = 5 10 | 11 | class CMDTEST_misc_batch < Cmdtest::Testcase 12 | def test_no_arg 13 | cmd "csope" do 14 | stdout_equal /.+/ 15 | stderr_equal /.+/ 16 | exit_status 1 17 | end 18 | end 19 | end 20 | 21 | class CMDTEST_dummy_project < Cmdtest::Testcase 22 | def setup 23 | import_directory "test/dummy_project/", "./dummy_project/" 24 | end 25 | 26 | def test_find_f 27 | cmd "csope -k -L -0 f -s dummy_project/" do 28 | created_files ["cscope.out"] 29 | stdout_equal /\A(.*\n){2}\Z/ 30 | end 31 | end 32 | 33 | def test_find_def_f 34 | cmd "csope -k -L -1 f -s dummy_project/" do 35 | created_files ["cscope.out"] 36 | stdout_equal /\A.+#{$f_definition_line}.+\n\Z/ 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/dummy_project/h.c: -------------------------------------------------------------------------------- 1 | #include "h.h" 2 | #include 3 | 4 | double h(int i) { 5 | if (i < 100000) { 6 | return rand() % i; 7 | } else { 8 | return i / 10; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/dummy_project/h.h: -------------------------------------------------------------------------------- 1 | #ifndef H_H 2 | #define H_H 3 | 4 | extern double h(int i); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/dummy_project/main.c: -------------------------------------------------------------------------------- 1 | // @BAKE gcc -o dummy.out main.c h.c 2 | #include 3 | #include "h.h" 4 | 5 | int f(void) { 6 | int r = 0; 7 | for (int i = 0; i < 100; i++) { 8 | r += (int)h(r); 9 | } 10 | return r; 11 | } 12 | 13 | 14 | signed main(void) { 15 | return f(); 16 | } 17 | --------------------------------------------------------------------------------